News

My Stats

  • Posts - 21
  • Comments - 20
  • Trackbacks - 0

Twitter












Recent Comments


Recent Posts


Archives


Post Categories


 

Command passing is a handy way to execute pieces of code on specific threads. The idea is simple enough: Write a command into a buffer and that command then gets executed on some specific thread that monitors that command buffer. This paradigm is used in graphics APIs like DirectX and OpenGL, for instance. This allows you to split your data into working sets that are owned by a single thread and must maintain their state over a specified time period.

In the graphics engine I’m developing at Raccoon Interactive we’re using a couple of separate data sets that should change only at specific synchronization points but we don’t want the other threads to stall until that point is reached.

In our case the high-level graphics rendering thread has it’s own data set that controls the graphical representation of the scene, i.e. the scene graph. The scene graph consists of a node tree with leaves referencing scene primitives like meshes and lights. Meshes use low-level renderer primitives like vertex buffers, materials and textures that are bound to a low-level rendering API, such as OpenGL, through an abstraction layer. Operations against this low-level API are executed on a dedicated thread.

Each different level abstracts thread communication with the help of wrapper classes, so from the point of view of the developer you’re just calling methods on objects. This makes writing algorithms that operate on the scene graph or the graphics primitives much easier because you don’t need to lock your resources as they are modified only at pre-specified points in time.This also means that different sub-systems can continue to run in parallel even though, from a user’s point of view, everything seems to happen synchronously.

The command buffer can be found at the heart of all this communication. I’ve designed a custom implementation that simply consists of a block of memory into which function parameters and the function to call, itself, are stored. The reader of the command buffer then reads this block of memory and calls the associated function with the parameters found in the memory block reserved for the command.

The command buffer implementation in our engine is very C-like, I must admit, but it serves our purpose more than well. To write a command into the buffer you do the following.

RRCommandBuffer::RRCommand<
    sizeof( RRInt_t )> cmd( &CmdMyCommand, pCommandBuffer );
cmd.Set<RRInt_t>( 1 );
cmd.Send();

The RRCommand class abstracts mapping and unmapping of the command buffer as well as writing the command arguments into the buffer. Its constructor takes a pointer to the command function and the command buffer into which the command should be written. We also pass the size required by the command arguments as a template argument, so the class knows how much space to allocate for this command.  All commands are written into a byte aligned memory buffer. Because assignment operators cause us trouble on systems that expect memory to be properly aligned we’re forced to copy the arguments into the command buffer by using a simple memory copy (aligning the arguments according to the worst case scenario would also work, but it would require significantly more memory).

To execute the commands we simply do the following.

pCommandBuffer->ExecuteCommand( true );

Passing true to the method makes it execute all the commands in the buffer. Otherwise, only a single command would be executed by a single call to ExecuteCommand.

The command itself is defined by the function CmdMyCommand, as is shown in the next code snippet.

void CmdMyCommand( RRCommandBuffer::RRInputCommand &rCommand )
{
    RRInt_t arg = rCommand.Get<RRInt_t>();

    // ...
}

As you can see, the command receives a single argument rCommand that provides access to the command arguments. The convention is that the command should read out all it’s arguments with consequent calls to Get at the start of the function. This is to avoid issues with reusing the temporary argument store from which the arguments are read.

That’s about it. This simple command sending mechanism has helped me a lot in creating abstraction layers to hide tedious thread communication. The same could most likely be implemented by using lambdas but I haven’t tried it because we’re currently tied to the lowest common denominator that is the Android NDK compiler, not to mention other even more limited compilers that we might have to support in the future.


 

The typical way to check for whether anything has changed in the view when you’re navigating away from a page is to bind a method to the change event of each input and to set a flag if this has happened. This flag is then checked when leaving the page and a notification is shown to the user if the flag is raised. This is all good but it does not take into account things like changing the order of inputs and changing values back to their original values. Also, creating dynamic elements makes this way of doing things a bit tricky because you have to add registering of the handlers to each method which adds new elements.

Just recently I had to implement this kind of checking. The implementation makes use of jQuery and has been tested with ASP.NET MVC but I don’t see any reason why it should not work with other platforms as well (at least with some minor changes). So without further ado, here’s the code.

/**
The variable contains all the values of the new as found by the previous call 
to storeViewValues. */
var viewValues = []; /** Set this to true to enable dirty-checking for the current page. This is also set when registering change checking for the view. */ var enableDirtyCheck = false; /** Collects all view values and returns the array. */ function collectViewValues() { var newViewValues = []; // Store inputs. $('input:enabled').each(function () { if ($(this).attr('id') != null && $(this).attr('id') != '') { // Ignore the ones that have '.' in their IDs. These are not part
// of our input values, since they are not allowed by // MVC when generating inputs.
var id = $(this).attr('id'); if (id.indexOf('.') < 0) newViewValues.push({ selector: 'input', id: $(this).attr('id'),
value: $(
this).val() }); } }); // Store select values. $('select:enabled').each(function () { var that = this; if ($(this).attr('id') != null && $(this).attr('id') != '') { $(this).find('option:selected').each(function () { // Ignore the ones that have '.' in their IDs. These are not
// part of our input values, since they are not allowed by // MVC when generating inputs.
var id = $(that).attr('id'); if (id.indexOf('.') < 0) newViewValues.push({ selector: 'select', id:
$(that).attr(
'id'), value: $(this).val() }); }); } }); return newViewValues; } /** Stores the current view input and select values to viewValues. */ function storeViewValues() { viewValues = collectViewValues(); } /** Checks for changes in the view. You must call storeViewValues when the view is fully loaded before calling
this method. */
function checkChanges() { var hasChanged = false; if (enableDirtyCheck) { // Collect current input values. var newViewValues = collectViewValues(); if (newViewValues.length != viewValues.length) { hasChanged = true; } else { // Check values. for (var i = 0; i < newViewValues.length; i++) { var newViewValue = newViewValues[i]; var viewValue = viewValues[i]; if (newViewValue.id != viewValue.id) { hasChanged = true; break; } if (newViewValue.selector != viewValue.selector) { hasChanged = true; break; } if (newViewValue.value != viewValue.value) { hasChanged = true; break; } } } } if (hasChanged) return "The page contains modifications!"; return null; } /** Call this method at the end of the current view if you wish to enable dirty
checking for the view. */
function registerDirtyChecking() { $(document).ready(function () { // Default to checking whether the view is dirty or not. enableDirtyCheck = true; // Store existing values. storeViewValues(); window.onbeforeunload = function (e) { var ret = checkChanges(); if (ret != null) { e.returnValue = ret; return ret; } }; $('form').submit(function () { enableDirtyCheck = false; }); }); }

The implementation takes into account that Internet Explorer shows the message even when you return null from the onbeforeunload handler, which actually works on Chrome, for instance. I also added setting of enableDirtyCheck to false when submitting the form, to ignore the message when we’re actually submitting the changes.

To use the code, simply include the bit of code in your view and call registerDirtyChecking at the end of the view. This forces the document ready handler to be added as the last one to be called (if other document ready handlers don’t add new document ready handlers themselves, that is).