LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 04-27-2005, 02:38 PM   #1
bretzeltux
LQ Newbie
 
Registered: Oct 2003
Location: Montreal, Canada
Distribution: Fedora Core 2
Posts: 23

Rep: Reputation: 15
UI: Events propagation design model


Hi there long time not showing meself here :-)

I have a very big and difficult question - and not expecting any real answers - but I am trying here because after googled all the way about my question, here I am and I will try other forums or very specialized free support discutions website....

First of all, I put which env I am writting my project, and I already asked similar question.

Language: C++ ( and some external C libs ):
Text-console-mode using ncurses
External libraries: pthread, sigc++-2.0, ncurses and maybe dl ( dlopen stuff )

Thus, I am writting a C++ User-interface framework using the above stuff.
But one thing is really stopping me in the design: The events propagation design model in the multi-thread env, and the problem of propagation of any events into the object hierarchies in the application framework.

I've already made a failed test: see [URL=http://ncdk.sf.net]ncdk
And read the API DOCS for the sources and the object-tree model. It is not the object-tree but the infamous events-propagation model.

Starting with a events simple design in single thread env:
Code:
     [ Application central get-events loop ]
                 |                   |
                 |       [KEY, MOUSE, SIGNALetc... events ]
                 |                        | <<== classify event 
                 |              [Propagate event trhough Active widget/object child-to-parent]
                 |                        | << or 
                 |              [Propagate event through registered objects ]
                 |                        |
                 \\< -------[dead-end of the "unconsumed" event propagation]
Thus not too difficult to implement that design as I did in the past in MS-DOS.
But in a multi-threaded environment, it is NOT feasible that way.
Any object/widget can be created and living in a different thread and must recieve as well the key,mouse, signals events from the application's central loop... And can trigger own events to be propagated from the central application getevent loop :-)

So
mutex/waitcond/lock-unlock (non recursive tho ) must be placed at the strategic and sensible points and not be recursive into its self-thread...

I tried to get and read the so X11 sources but no clue where to start --- my brain was melting just trying to find a startpoint about events propagation!

KDE/QT are just sitting above the X11 technology --- can't get any clue there.

Any "GOD"-programmer kind enough to help me ? ( hints, advices,guidelines, URLs)

Thanks
Bretzel
 
Old 05-03-2005, 05:27 PM   #2
LogicG8
Member
 
Registered: Jun 2003
Location: Long Island, NY
Distribution: Gentoo Unstable (what a misnomer)
Posts: 380

Rep: Reputation: 30
Let me just see if I have your situation correct
You are writing a text mode multi-threaded gui application
You have a single thread that is a loop capturing events and you want it to propagate those events to various gui objects.
that may be running in different threads.
Object creation is dynamic so the main thread must be notified of the existence of the threads in a non-racy way.

If I were in your shoes I'd create a linked list of call back functions and a mutex object to protect the linked list.
Whenever you create a new gui object you register a callback function in a large list. When ever the main thread
receives an event it walks the list calling the callbacks. You can have a hierarchy of gui objects and you can walk
through objects until the event is handled.

In pseudo code:
Code:
/* Main thread */
while (1) {
    Event e = GetEvent();

    if (e == NULL) {
         break;
    }
    PropagateEvent(e);
}

/* PropagateEvent */
void PropagateEvent
{
    LockMutex(gui_mutex, wait_forever);
    node = gui_list_head;
    while (node) {
        node->callback(e);
        node = node->next;
    }
    UnlockMutex(gui_mutex);
}

/* All the GUI objects do something like */
gui_object_creation()
{
    /* Initialization */

    /* Ready to handle events */
    AddCallback(function);
}

AddCallBack(int (cb)(Event))
{
    LockMutex(gui_mutex, wait_forever);
    node = new node;
    node.setCallback(cb);
    insertnode(node);
    UnlockMutex(gui_mutex);
}
 
Old 05-03-2005, 11:41 PM   #3
bretzeltux
LQ Newbie
 
Registered: Oct 2003
Location: Montreal, Canada
Distribution: Fedora Core 2
Posts: 23

Original Poster
Rep: Reputation: 15
Hi LogicG8,

I must thank you very much for your reply, you know, i 've asked that question in several places over the net and you are the very first kind person who talk to me about my question :-)

I think I will re-put the API-DOC of ncdk, and an other experiment/exercise about the same project ( named felix ), at ncdk.sf.net .

What I have troubles with is that I've not mastered the pthread yet, so the "felix" experimentation include more advanced ( in my situation ) thread related stuff, such as a controler class that wraps a thread, mutex, and condition-wait technique applied to an application's events queu controler, and also a curses::screen io-queu controler. But i am scared of :
For objects created into the same thread as either the application's events queu controler thread or the screen IO controler thread, there will be dead-locks because those mutex-lock must not be recursive into the same thread.

Regarding events: I have to take in account the fact that objects in "callback state" will most of the time trigger other events to be put into the "global" events-queu while the queu access is locked during the "propagation" ... ouch!

So if the queu itself is not protected and multithread safe ( as the std::containers are supposed to be in that case ) and the queu is (pseudo-)async writeable, then no problems there.
But the central loop must be notified about events in the queu... Thus a controler class that implements the cond-wait, signals ( or awakes)the central-propagator thread that there are events in the queu, ready to be propagated. That raises another problem which I can't elaborate here for saving your time and space...

I dunno how but what you did by answering me is that I've just found a solution, thanks to your suggestion and your intervention:

What I am thinking is that objects/widgets classes that generate events ( thus - objects that register themself to be events generators )should have a "local hold-buffer of events queu" and when the central-loop finishes the propagation of the events ( consumes the global events queu ) signal the objects to "put" their held events into the global events-queu. When all the transfers are finished, then re-do the events propagation process, and-so-on :-).

This way it is now very straitforward to identify and implement object classes which interface the KEYBOARD, MOUSE, TERMINAL,SYSTEM events as "registered events generators objects" :-)

( I don't want to re-read meself in case that I can't understand anymore what I said :-)

Cheers,
Bretzel
!!
 
Old 05-04-2005, 10:26 AM   #4
LogicG8
Member
 
Registered: Jun 2003
Location: Long Island, NY
Distribution: Gentoo Unstable (what a misnomer)
Posts: 380

Rep: Reputation: 30
Quote:
I dunno how but what you did by answering me is that I've just found a solution, thanks to your suggestion and your intervention:
I'm glad my incoherent ramblings and half-baked ideas managed to help you .

Quote:
( thus - objects that register themself to be events generators )should have a "local hold-buffer of events queu" and when the central-loop finishes the propagation of the events ( consumes the global events queu ) signal the objects to "put" their held events into the global events-queu. When all the transfers are finished, then re-do the events propagation process, and-so-on :-).
Okay, I think I understand now, but propagating events that way will mean walking the object
hierarchy twice for each event. Once for the event and once to signal each object to put its new
events into the event queue. I don't like it because it just about duplicates the functionality of
the event propagation it means to help. It's like a queue_events event. Complexity is the bane of
computer science, special cases are a major source of complexity.

Rather than having local queues for each object why not have two queues that look like one queue.
You have a public queue that objects can add events to with its own locking and a private queue
that is accessed only by the event propagation thread and needs no locks. When an event is
finished being propagated the propagation thread waits for the public queue to become available,
takes the lock, and puts all the events from the public queue into the private queue. Thus getting
the new queue events becomes O(1) appending one queue to another instead of O(n) where n is
the number of objects to signal. Other threads can be merrily adding events while your thread
propagates the current event from its private queue and all is well in the world.

This of course assumes that all the events are distinct and atomic. If you need to guarentee the
exact ordering of multiple events in the global queue then you will need some kind of local queue.
This fits in my 2Q model as well though. An object can build up a queue of events and add them
to the queue in one fell swoop.

I took a look at your project page and it looks fairly interesting. Unfortunately many of the links
were broken. I'd have liked to see how the API was laid out.

One more thing, you may want to look at a project called "TWIN". TWIN was a Text-mode WINdow
manager. You might be able to get some cool ideas from there. I don't know if they are still around.

Cheers,
Adam
 
Old 05-05-2005, 09:12 AM   #5
bretzeltux
LQ Newbie
 
Registered: Oct 2003
Location: Montreal, Canada
Distribution: Fedora Core 2
Posts: 23

Original Poster
Rep: Reputation: 15
Quote:
Originally posted by LogicG8
I'm glad my incoherent ramblings and half-baked ideas managed to help you .



Okay, I think I understand now, but propagating events that way will mean walking the object
hierarchy twice for each event. Once for the event and once to signal each object to put its new
events into the event queue. I don't like it because it just about duplicates the functionality of
the event propagation it means to help. It's like a queue_events event. Complexity is the bane of
computer science, special cases are a major source of complexity.
Yes I agree with you. But since my ui project is not intended to be an heavy-wieght GUI with tons of objects, just a single application
framework with cool features such as tags-like embedded attributes formating text; threads and maybe other goodies;...
I have to tell that this project is an exercise and a learning curve, experimentation for my own personal goals, linux programming skills.
Especially, to put that framework at the C++ programming level because I love C++ And it has to be kept simple in the design and development and finally simple to use in the price of lacking lots that TWIN's deep features levels.


Quote:
I took a look at your project page and it looks fairly interesting. Unfortunately many of the links
were broken. I'd have liked to see how the API was laid out.
Duh! i have totally wiped out the web contents and restarted a new one and didn't realize that I given you the link to see the deleted contents! my fault!
If you are still curious to see what I've tried, you can go again at ncdk apidocs: 1:ncdk, 2:felix but I warn you that those "essais" are just "essais" and may contains good ideas in their peices of code and features that's all.

Quote:
One more thing, you may want to look at a project called "TWIN". TWIN was a Text-mode WINdow
manager. You might be able to get some cool ideas from there. I don't know if they are still around.
Wouah! I've just finished compiling it and browsed its core libs. ...And no, I am not intending to write that complex environment framework! I have no skills (yet?) of that level - But yet I understand most of his code and design tho :-), My project, as I said above, is meant to be simple to write and use.

yeah, it is a beautyfull project and I think it is worth to start using it and get some design pieces of this project, and thanks the author and speak to him about what I use from his ideas - if I do need some of his stuff...


Cheers,
Adam

Cheers,
I realize that you are a very kind person and it is a real pleasure to talk to you about this kind of subject, and also I realize that I have a long way of learing before I can master several of the linux/multitask system aspects.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Linux for Graphic Design, web design, and publishing maelstrom209 Linux - Software 8 07-17-2011 11:35 AM
Capturing X Events phrontist Linux - Software 1 10-28-2004 08:56 AM
Does Samba have Events smurf Linux - Networking 2 02-12-2004 02:00 AM
Events In KDE LOUDSilence Programming 3 11-23-2003 02:41 AM
DNS Propagation penguinz Linux - Networking 4 07-29-2003 03:06 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 05:45 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration