Monday, April 23, 2012

Thinking more about how to build an object messaging system.

I am at the point in my dataobj project where I am trying to bootstrap  the low level libraries into a set of objects that intelligently perform the actions I want.

The first thing I want is to create just a pulse object and a debug out object so that I can generate a single pulse, output the result on a debug print.  After that I was thinking of creating a file object and a network object and create a little web server.

But I am having trouble thinking about how this whole thing fits together.  So I need to break it down into smaller chunks.  Let's look at what happens when a message updates a property.

At the lowest level a property will have to perform the following when an UPDATE message comes in.

This is just pseudo code for now.

Property Func_change( This, value, msg, state)
   Set(This, value);

    return Propagate_msg;

This is the default for any object, so there should be a generic handler that does this for any property where no special processing needs to happen.

All properties would be a member of a class that describes , so if they get a draw message they should not handle the message, instead passing the message up to their parent class.

All this means that there is a higher level function calling down with a message that is being dispatched.

On return the changed value will only be propagated in the manner that the return value  designates.    This means that the Set, or update or whatever function that is updating the value will not instantly change the value.  The value is not changed until after the function returns.

Setting a new value will replace the old value in the object, and ref_count-- the old value.  The old value will not place itself on the free list until it's ref_Count hits zero.   The data value passes by reference, so there might be thousands or millions of objects and messages referring to the same data value.

When the value has changed, and we are propagating the event.  Then we need to walk the subscribed list and create a series of messages that refer to the current data object, the referring data object, and the data object and an UPDATE state should be sent.  Each message generated will use a reference to the value and do a ref_count++.

A property can also send a message to itself, with itself as the sender and receiver, a data value, and a custom state value.    This message can be scheduled to be delivered milliseconds, seconds, days, or years later.  This allows the system to act just like a state machine with timed actions.  The function called to set this up will handle the ref_count++.

When a message is delivered it will be dispatched at a higher level and any intercepts taken into account.  As soon as the message is ready to return from being handled, it will do a ref_count-- on the data object and nodes to let them go.   If their ref_count drops to zero they will add themselves to a free list.

The reason for only ever replacing a data value instead of updating that value is for threading and messaging purposes. If the data value will never change, then you can send that same exact data object to thousands of other messages and objects and get a huge speedup.  If the value can change, then you cannot send it as a reference, you have to make a copy, and copying large strings is very slow.

It may be possible to create a diff text object that will layer on top of other data objects,   So the stack of objects can generate the interface of a single text object.  This helps with text boxes that are appending, so that the new bit is put into a text object, the text object can then point at the rest of the stack as an append, and  this new reference be passed down the line without actually doing more than working with a little text and a reference.  Anything pointed at something lower down in the stack will see the text the same old way still.  It would even be possible to create a copy of just the top object if you need just the latest update.  the lower level objects can be slowly merged upwards as their ref_counts drop to zero.


Future graphics support.  Once I get the low level all working, I can then build a set of graphical objects on top of the system.  This could also be some sort of web object that translates everything into html 5 to give the program a web interface.

How do I draw my properties as text boxes ( or other control) in a window?

When I create a property I can also create a text box control that subscribes to the properties data value.  At this time I also set the controls values.  When the control gets a message that an update occurred a flag is set that will lazy update the control when the controls are walked later.  A rapid refresh could also happen if it is important for that control to be quickly updated.  Even then the control should not be updated faster than the screen refresh rate.   And, of course, the OS control that actually displays data only exists when the window it belongs to exists and the control is visible.
Not all properties need to have a control, but every control needs to have a property.    The control will have a set of properties as well that could be set and subscribed to.

This control object always exists, even when the control is not visible on the screen.  But the OS level control in this object only exists when the

The controls all belong to a window.



You should be able to pull out a control into another window and create an alias control in the new window.  This is basically a new control that subscribes to the same data value in the

At the graphical layer you can build a set of subscriptions  by drawing lines between these alias objects.  These subscriptions only apply to this one window.  So you can pull all the enables of your gadgets out into a view, wire them up and when you click the first one, all the rest turn off.  But that change does not propagate out of this window.



How do I override the intercept for a control or property?

The object will have a list of intercepts, much like a list of subscriptions.  < need to think about this more.>

Why do I want to intercept a data value?

When you want to change the behavior of an object you need to override how it works.


This document seeks to explore how a cross platform messaging engine should work.

To start you have to have a base system that will be just enough to set everything up.

This is essentially the root class that is the mother of all classes.

From this you can subclass and load in a module that extends the capablities of the core system.

The base system must have the capability to search a given path for loadable modules.

As each module is loaded in they will just register themselves.

Once all the modules are loaded they will be ClassStarted and any that have dependencies that cannot be met will report this and then be unloaded.

All that a class is, is a set of messages and a private data structure of it's own classes type.

Every data element is a property of something else.

New properties can be arbitrarily added to a class.

You can subclass an existing class by encasulating that class, adding new properties to the existing class and registering messages that you handle.
One can also override the existing classes messages with your own message handler before passing that message to a sub class.

For instance,  the base class may be tcp, but you could wrap a TCP allow that would only allow certain ranges of IP addresses to connect.

Or you could wrap tcp inside an HTTP protocol object that would translate http requests into the proper sets of tcp commands in order to perform a proper request.

multithreaded I/O

Single thread of messages in a particular application.  multiple
applications running at the same time talking through a core.

Allows full use of computing resources.

-- -- --

multithreaded I/O

Multithreaded messages.

Each instance has it's own thread.

Problem, nothing is keeping events from happening in the "right" order.

-- -- --

Think of a message passing system like a

-- -- --

Loadable modules.

Search a directory tree for configuration files.

Load in all the xml files that define the

-- --

Start the process.

Initialize the base class named object.

Load in directory object, file object, and xml object from a fixed

Load in a configuration file.

This configuration file will specify what directories to seach in for objects.

If this is the first time running

       then search for directories.

       Open, read, and parse into a data structure each objects config file.

       Order the list of dependencies.

otherwise attempt to load in everything defined in the list of things.

Load in the list of things in the order specified in the list of dependencies.

If you scanned for things, then save the list of stuff you found as a
configuration file.


No comments:

Post a Comment