PeerOS available for download

Anything and everything that's related to OGRE or the wider graphics field that doesn't fit into the other forums.
User avatar
Occulis
Halfling
Posts: 91
Joined: Tue Mar 29, 2005 7:29 pm
Location: Houston, TX

PeerOS available for download

Post by Occulis »

PeerOS (download - 5.5kB) is a simple but powerful messaging system I use in C++. I was having trouble finding a library which easily implemented the three important classes (the publisher, the message itself, and the handler). Everyone seemed to over-complicate it.

*Edit*: Placed on the Ogre3D wiki under PeerOS

I hope I'm not reinventing too many wheels. It works for me, though I suspect there is a bug or two hanging out in the code.

Here is a sample of the peeros_main.cpp. It shows how to set up multiple handlers to process messages of various class types. I hope this is easy to read:

Code: Select all

#include <iostream>
#include "peeros.h"
#include "peeros_main.h"

using namespace std;

// 1853 is an arbitrary number:
#define TOPIC_EXAMPLE_INITIALIZE    1853

// ======================================================================
// MAIN
// ======================================================================
int main(void)
{
    // We only have one publisher:
    CMPublisher_Keyboard        keyb;       // Announces keyboard events

    // But there are three handlers who read the publisher:
    CMHandler_Camera            h_cam;      // Handles camera messages
    CMHandler_CameraAndWidgets  h_camwid;   // Handles cameras and widgets
    CMHandler_Widget            h_wid;      // Handles only widgets

    // Two example messages.  One about a camera, one about a widget.
    // Notice how they both are talking about topic TOPIC_EXAMPLE_INITIALIZE
    CM_Camera       msg_cam;    // An example msg about a camera
    CM_Widget       msg_widget; // An example msg about a widget

    msg_cam.m_topic     = TOPIC_EXAMPLE_INITIALIZE;
    msg_widget.m_topic  = TOPIC_EXAMPLE_INITIALIZE;


    // Setup relationships.  Because each of the message instances, CM_Camera
    // and CM_Widget, have their topics set to TOPIC_EXAMPLE_INITIALIZE,
    // all three handlers will *only* answer messages about
    // TOPIC_EXAMPLE_INITIALIZE.  See cm_defs.h for a couple examples.
    keyb.Subscribe(h_cam, msg_cam);
    keyb.Subscribe(h_camwid, msg_cam);
    keyb.Subscribe(h_wid, msg_cam);

    // Publish the first message.  It will be handled by any subscribers who
    // can receive a CM_Camera message.  Note: It will only be delivered to
    // subscribers whose subscribed topic matches msg_cam.m_topic!
    keyb.Publish(msg_cam);

    // Now publish a widget message.
    keyb.Publish(msg_widget);

    // Now change the camera topic to CM_TOPIC_NONE, so all listeners
    // who can receive *any* CM_Camera message will be published to.
    // It's up to them if they want to do anything with it:
    msg_cam.m_topic = CM_TOPIC_NONE;
    keyb.Publish(msg_cam);

    return 0;
}

Here is the output from the example program. It shows one publisher (CMPublisher_Keyboard) sending messages of varying types (CM_Camera and CM_Widget) to all subscribers.

Code: Select all


PeerPublisher::Subscribe(ob, msg topic:1853)
PeerPublisher::Subscribe(ob, msg topic:1853)
PeerPublisher::Subscribe(ob, msg topic:1853)

CMPublisher_Keyboard::Publish(1853, 0)
CMHandler_CameraAndWidgets::process(CM_Camera *): Widgetizing at '0.111, 0.511, 0.666)!
CMHandler_Camera::process(CM_Camera *):  XYZ (0.111, 0.511, 0.666) successfully processed!

CMPublisher_Keyboard::Publish(1853, 0)
CMHandler_Widget::process(CM_Widget *): Cheese 'meunster' dispensed!
CMHandler_CameraAndWidgets::process(CM_Widget *): Placing 'meunster' cheese onto pizza.

CMPublisher_Keyboard::Publish(0, 0)
CMHandler_CameraAndWidgets::process(CM_Camera *): Widgetizing at '0.111, 0.511, 0.666)!
CMHandler_Camera::process(CM_Camera *):  XYZ (0.111, 0.511, 0.666) successfully processed!

It's easy to write very complex relationships with this setup, or leave it very simple. Hope this helps someone.

There is some good documentation for it, but it's on my team's wiki which is private. I'll convert it to plain HTML if a couple people express interest.

Note: The Makefile has only been tested under Debian, but I use PeerOS under my Win32 projects as well.
Last edited by Occulis on Sat Nov 10, 2007 2:34 pm, edited 2 times in total.
User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
x 179

Post by jacmoe »

Woohoo! Just what I need! :D

What's the license on this gem? :)
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
User avatar
Occulis
Halfling
Posts: 91
Joined: Tue Mar 29, 2005 7:29 pm
Location: Houston, TX

Post by Occulis »

Sorry, didn't include the license. It's free as in beer and free as in speech. Glad you can find it useful! :D
User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
x 179

Post by jacmoe »

Occulis wrote:Sorry, didn't include the license. It's free as in beer and free as in speech.
If that's the case, then this would be best put on the OGRE Wiki. :)

Occulis wrote:There is some good documentation for it, but it's on my team's wiki which is private. I'll convert it to plain HTML if a couple people express interest.
Then you don't have to convert the documentation, if your team wiki is MediaWiki. :wink:
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
Tenttu
Halfling
Posts: 74
Joined: Mon Dec 13, 2004 1:56 pm

Post by Tenttu »

Does anyone still have the package? Would be nice to put the source into wiki.
User avatar
Occulis
Halfling
Posts: 91
Joined: Tue Mar 29, 2005 7:29 pm
Location: Houston, TX

Post by Occulis »

I updated the link in the first post
Slicky
Bronze Sponsor
Bronze Sponsor
Posts: 614
Joined: Mon Apr 14, 2003 11:48 pm
Location: Was LA now France
x 26

Post by Slicky »

Interesting - I think I almost get it.

Is there any documentation that shows in a real world way what this could be used for? I have a feeling there is a good concept here if I could just grasp it.
User avatar
Occulis
Halfling
Posts: 91
Joined: Tue Mar 29, 2005 7:29 pm
Location: Houston, TX

Post by Occulis »

Hey Slicky, are you familiar with the book Design Patterns? Here's what I wrote, using keywords I hoped would stand out to people who are. Also, here's a great wikipedia page on it.
The Peer Object Subscriber set of classes help us set up an Observer (aka Publisher-Subscriber) design pattern.

This solves the problem of complex message handling in a large C++ application with many small pieces.
If you're not, here's an example for how you could use PeerOS.

  • My game generates a message like "user {X} has logged in"
  • This message is going to have actions occurring in many modules (play a sound on a client machine, possibly open a chat window if your player chat settings have Buddy Pounce options, enable server-side logging / cheat detection, and so on).
  • You do not want to have a big controller decide who to send messages to. You want to add subscribers "on the fly" to handle various messages. For instance, at runtime you disable some feature: this unloads an optional dynamic library and removes its listener. Now your game runs faster because 1 less listener is processing "user has logged in" messages.
Hope that helps!
Slicky
Bronze Sponsor
Bronze Sponsor
Posts: 614
Joined: Mon Apr 14, 2003 11:48 pm
Location: Was LA now France
x 26

Post by Slicky »

Thanks for the explanation. With the example I get it. It sounds like a more elegant system than running through a bunch of checks all the time.
User avatar
robagar
Halfling
Posts: 77
Joined: Tue Oct 24, 2006 1:52 am
Location: Tropical North Queensland

Post by robagar »

Nice one Occulis :) Is PeerOS thread-safe? ie can messages be published on one thread and consumed on another?
User avatar
Occulis
Halfling
Posts: 91
Joined: Tue Mar 29, 2005 7:29 pm
Location: Houston, TX

Post by Occulis »

Robagar, no clue. I haven't reviewed the code in quite some time! Are you familiar with making things thread-safe? If so, please take a look at it and let me know what you think. The source should be very small.
User avatar
robagar
Halfling
Posts: 77
Joined: Tue Oct 24, 2006 1:52 am
Location: Tropical North Queensland

Post by robagar »

yeah, I'm familiar with thread safety, but no expert. It does look to me like it is not thread safe - I don't think std::list is itself thread safe for concurrent insertion & reading, and there's nothing to stop subscription to messages during the publishing loop. (whether that would actually result in bad behaviour is another thing)

Wrapping the subscription and publishing sections in a mutex of some kind would make it safe, but then the thread calling Subscribe would block until the publish loop exits.
Vectrex
Ogre Magi
Posts: 1266
Joined: Tue Aug 12, 2003 1:53 am
Location: Melbourne, Australia
x 1

Post by Vectrex »

is this basically the same as using something like Boost::Signal? I use signal a bit and it's nice and handy to fire off events. The queue stuff is different than signal though? I don't like signal has a queue.
User avatar
PolyVox
OGRE Contributor
OGRE Contributor
Posts: 1316
Joined: Tue Nov 21, 2006 11:28 am
Location: Groningen, The Netherlands
x 18

Post by PolyVox »

I would also be interested in people opinions on how this compares to something like signals and slots. Is it an alternative or a complement? Should/could the two be used in parallel? What are the advantages of each?

I've enjoyed Qt's signal-slot mechanism and boost's appears to be more sophisticated (allowing groups, etc). But in PeerOS I find the concept of topics intreging and possible quite powerful. I might have a look through your source code.