See the Userís Guide for more discussion.
This adds the specified commission to the
list of commissions making up this parliament, sorted by the low 16 bits of its schedule
member. If there are identical
schedule values, the order is unspecified. If you really need to control the
order, use different values; the common schedule_t values are spread very
far apart to give you room to make each one unique if necessary.
It is allowed to add multiple copies of the same
commission, even if all the fields are the same. That
would not be very useful, however. Normally something will be different: different ministers working on the same job, or
the same minister looking at the message both early and late in the list. The very purpose of the
id field is to let you tell them
apart when there are multiple
commissions for the same
remove are serialized when calls are made from different threads. Calls to
remove will not affect an in-progress traversal of the list from a running call to
handle_message, from the same or different
thread (but see notes in ministerís Userís Guide for advanced techniques).
See also: remove.
These forms of the
add function (you can pass 2, 3, or 4 arguments) can be handier than the
form that passes a structure, and is more efficient too. Consider the code (Listing 1):
commission c; c.appointed_minister= this; // assigns pointer to baro c.range= theRange; c.schedule= low(Normal); c.id= 1; add (c);
The call to
add causes the
commission structure to be copied into the list,
which means the copy constructor is called on the baro. The value
c.appointed_minister had to be created to begin with, and later destructed. Manipulating a
involves atomic operations, which are very expensive to the CPU.
By passing in the raw pointer and letting
add assign it directly to its final location in the array,
it saves the constructor and destructor of
c, eliminating two atomic operations.
add (this, theRange, low(Normal), 1);
This call to
add with individual parameters (Listing 2) will accomplish the same
thing, without the need to create a local structure.
If you do need to do something else to the
commission that is not covered by the parameters, you
can still use this form! The function returns a pointer to the actual location to which it was added in the list, and you can
manipulate the values in-place. However, this opens up thread-safety issues, that are discussed in detail under the
find function. Suffice to show a couple examples here, and assure you that the thread safety is
add (this, theRange, low(Normal), 1) ->rangefunc=theFunc; locked_commission c= add (theMinister, theRange); c->id= 2; c->appointed_minister.own(true); // set ownership flag of the baro
This function returns a pointer to the location of the matching
commission in the list. If there is more
than one (not a normal situation—if the same minister is inserted multiple times in the same list, they should have
ids so the minister can tell which context it is being called in) it returns a pointer to one of them with
no error or indication that it is not unique. If there is no match, the return value will evaluate as a boolean
just like a primitive pointer type.
There are inherent threading issues with having a pointer into the list, since other threads may
remove while this thread is still holding it. In this design, that is not to be
tolerated! Obviously, you can use the listlocker to explicitly deal with it, but
you donít even need to do that because the code is fully automated, by the use of a proxy object instead of the
The return value from
find and from
add is a value of the
class, which acts like a pointer to the underlying
commission, but also implements a destructor to release
the lock when it goes out of scope.
locked_commission c= find (theMinister); // locate my commission record if (!c) return; // acts like a null pointer if not found c->appointed_minister= differentMinister; // can change anything! c->id= 2; c->range << WM_WhatEver; c->schedule= always(c->schedule); // but use care changing this one // when c goes out of scope, the lock is released.
You should use care in changing the value of schedule in-place,
since the list is sorted by this value. It makes sence to set or clear the flag bits like ďalwaysĒ that donít affect the actual
ordering, and it is well-behaved to change the schedule value such that it doesnít change the commissionís order in the
list. But changing the schedule value to produce an out-of-order list will cause the list ordering to not be maintained
properly thereafter. (Note that this is the limit of the mis-behavior. The
message_parliament will not
itself cause a bad pointer, memory leak, or anything undefined. What your ministers do when called in the wrong order
is out of my hands.)
This matches the signature of the function in class message_tap,
and you can think of this function as overriding it, but this class does not derive from
message_tap. The intention is that a
class (such as eagduru)
will derive from both
message_parliament, with code in the former calling code in the latter.
But the classes are unrelated! Such is the magic of virtual functions in virtual base classes. When the two classes do wind up being part of the
same concrete class, the implementation will realize that they are the same function. However, you can link any choice of calling sibling (e.g.
an alternative to
message_tap) and any choice of implementing sibling (e.g. an alternative to
and get the same effect. You can aggregate different produces and consumers using the same interface with a horizontal mix-in approach,
rather than a vertical chain of derived classes, and acheive much greater code reuse with flexibility in choosing features. This is
a primary architectural concept in Tomahawk.
This function is implemented to iterate through the list of
commissions (added by calls to add)
and call the associated
ministerís administer_message function,
if applicable, to actually handle this message.
See the Userís Guide for details about the iteration and discussion of advanced techniques.
This will be called by handle_message if no commissioned minister handled the message.
Set it to the original WndProc of the window that was hooked by message_tap.
If deriving from both classes,
called from on_attach will do.
This removes commissions from the list of commissions making up this parliament. It will remove
those that match the
id field, or when
all commissions for the minister regardless of
id. It returns the number of commissions that were removed,
which might be zero.
See threading notes under add.