wiki:Tutorials/Advanced/Blackboards

Blackboards are more or less (network-transparent) areas of shared memory. They are a central mechanism for data exchange in MCA2. In Finroc they are less important, since objects of arbitrary types can be transferred via edges. Nevertheless, they are sometimes useful. Blackboards are available if you check out the blackboards plugin.

Types of Blackboards

In principle, there are two options of creating (and using) blackboards: globally and locally.

If you are unsure, locally (meaning inside of a module a group) is usually preferable, since this avoids naming conflicts. Furthermore, communication structure is better visible in Finstruct's data flow graph for application visualization - making it easier to determine who actually accesses the blackboard.

The blackboard mechanism involves clients and servers: The blackboard server contains the master copy of the blackboard data. Each module that intends to use a blackboard needs to create a blackboard client which is then connected to a server.

Write operations to blackboards typically require locks. Using asynchronous transactions, however, blackboards can be modified without locking them at all.

Only some read operations require locks.

Local Blackboards

Local blackboards can be found in the test program in plugins/blackboard/test:

Basically, you add a respective variable to the ports/parameters section of a component's header file - e.g.:

//----------------------------------------------------------------------
// Ports (These are the only variables that may be declared public)
//----------------------------------------------------------------------
public:

  /*! parameter value blackboard */
  blackboard::tBlackboard<float> parameter_value_blackboard;

tBlackboard has two relevant constructors: The first is meant for creating blackboards. It has quite a few parameters which allow to influence to which port groups (ControllerInput etc.) the blackboard's ports are added to.

If a group should forward a blackboard of one of its modules to the outside, you also add a respective variable to the ports/parameters section of the group (same as the code snippet above). Here, the second constructor taking a tBlackboard<T> reference is used: This will not create a blackboard, but rather forward the ports of the module's blackboard to the outside.

  • Note that tBlackboard and tBlackboardClient objects used for forwarding blackboard ports to group interfaces currently (and intentionally) cannot be used for blackboard access (e.g. using tBlackboardReadAccess and tBlackboardWriteAccess; however, this would be technically possible - if ever necessary and agreed upon).

You perform similarly, if a module or group is only supposed to use a blackboard: Instead of a tBlackboard<T> variable, you add a tBlackboardClient<T> variable to the ports/parameters section - e.g.:

//----------------------------------------------------------------------
// Ports (These are the only variables that may be declared public)
//----------------------------------------------------------------------
public:

  /*! Parameter value blackboard client */
  blackboard::tBlackboardClient<float> parameter_value_blackboard_client;

If, however, only read access to blackboards is required, it is recommendable to not create a blackboard client at all. Instead, a input port with the blackboard type T in a std::vector is sufficient - e.g.:

tSensorInput<std::vector<rrlib::simvis3d::tCoinElementDescriptor>> si_element_descriptors;

Connecting Local Blackboards

In the code, blackboards can be connected using the public variables in the ports/parameters section:

// in some group constructor...
parameter_value_blackboard_client.ConnectTo(parameter_value_blackboard);

In Finstruct, it should be possible to connect the respective ports as well. Note that there are two connections for each blackboard: a read-only and a write connection. It is possible to connect only one of them (as done in pBlackboardTest.cpp for testing purposes):

// connect modules with blackboard
blackboard.GetWritePort().ConnectTo(writer->bb_client.GetOutsideWritePort());
blackboard.GetWritePort().ConnectTo(async_writer->bb_client.GetOutsideWritePort());
blackboard.GetWritePort().ConnectTo(reader->bb_client.GetOutsideWritePort());
blackboard.GetReadPort().ConnectTo(reader->bb_client.GetOutsideReadPort());

This not really nice from the API. Usually, you should use the ConnectTo functions provided by the Blackboard objects.

Accessing Blackboard

Using blackboard client for modifying blackboard:

try
{
  blackboard::tBlackboardWriteAccess<float> bbw(client, std::chrono::seconds(4));
  bbw.Resize(8u);
  bbw[4] = 4.5f;
}
catch (const blackboard::tLockException& ex)
{
  // possibly do something here
}

For read-only access, a blackboard::tBlackboardReadAccess<float> object is used instead.

Global Blackboards (somewhat deprecated)

Creating a global blackboard server:

blackboard::internal::tBlackboardServer<float>* server =
    new blackboard::internal::tBlackboardServer<float>("Test Blackboard");

Creating a global blackboard client:

blackboard::tBlackboardClient<float> client("Test Blackboard", parent);
Last modified 4 years ago Last modified on 17.12.2014 14:08:02