<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wikidot="http://www.wikidot.com/rss-namespace">

	<channel>
		<title>Comments for page &quot;The Callback Hell&quot;</title>
		<link>http://250bpm.com/blog:24/comments/show</link>
		<description></description>
				<copyright></copyright>
		<lastBuildDate>Sat, 01 Aug 2015 21:43:43 +0000</lastBuildDate>
		
					<item>
				<guid>http://250bpm.com/blog:24/comments/show#post-2302831</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:24/comments/show#post-2302831</link>
				<description></description>
				<pubDate>Mon, 25 May 2015 00:13:56 +0000</pubDate>
				<wikidot:authorName>jerry</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>I've used my own State-Transition Paradigm for 15yrs now. I've been successful in keeping complexity down in my versions of financial telecommunication software (mostly stock exchanges), and Change management software</p> <p>What I did was to extend the STD to do more. I did this by including incoming events, transitions, and outgoing events. This allows a lot more expression in the story. In fact it nearly tells the whole story. The transitions can be compiled into routines (or &quot;Events&quot; in your definition).</p> <p>In my definition of STD an 'event' is something happening on the underlying socket (like a msg received), a user API routine call, or an 'internal event' being signalled.</p> <p>Internal events are usually part of the of a transition on Object A, issuing an event on Object B.</p> <p>I know this sounds weird, but think about how much code you could remove from nanomsg if your state diagrams looked like: <a href="http://westrick.com/Jerry/CubixSystem.pdf">http://westrick.com/Jerry/CubixSystem.pdf</a> .</p> <p>This is the method I invented to get a handle on the inherent complexity of async systems.</p> <p>Be interested in what you think&#8230;</p> <p>Oh, and yes, in this method, a socket can be assigned an STD per protocol, instead of one STD&nbsp;for all&#8230; Which seams to be the core of your problem.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:24/comments/show#post-2299081</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:24/comments/show#post-2299081</link>
				<description></description>
				<pubDate>Wed, 20 May 2015 10:52:05 +0000</pubDate>
				<wikidot:authorName>Martin Sustrik</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>+1 for not using threads at all.</p> <p>I wonder how the stuff even got so widespread in the first place. We had a perfectly viable model (processes&amp;pipes) even before threads so there was no obvious reason&#8230; except maybe, when you are coding a boring crud application, using threads generates a lot of fun. Not even speaking of job security :)</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:24/comments/show#post-2299075</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:24/comments/show#post-2299075</link>
				<description></description>
				<pubDate>Wed, 20 May 2015 10:40:35 +0000</pubDate>
				<wikidot:authorName>Klinkenbecker</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>Funny how this stuff goes around and around to be reinvented over and over. 20 years ago, I implemented a TCP stack and rapidly came to the conclusion it needed to be an FSM if it was going to be maintainable and extensible.</p> <p>I was fascinated by the discussion of events verses 'safe' callback handling. The former puts event (handlers) in a (single) queue, the later puts the event handlers in two distinct queues - the LIFO and the stack. They are both fundamentally the same paradigm, they differ only in how the queue(s) is(are) managed.</p> <p>I would argue that the 'safe' callback method is actually more dangerous for two reasons;<br /> a) because it splits event handlers between the LIFO and the stack &amp;<br /> b) because it depends on a high level of dev discipline to keep track.</p> <p>b) violates a fundamental rule that, despite all best intentions everyone is fallible.</p> <p>I have not reviewed code, but you will find that the 'cleaner' (i.e. cleanly abstracted) your event paradigm, the easier it will be for devs to use the pattern and thus, they will be less likely to spend energy implementing something else. 'Clean' abstraction means easy setup, simple APIs, transparent architecture, event queue management (typically at least 3 levels) and queue visibility (debugging and system handling).</p> <p>I have since taken the (event) paradigm to the ultimate conclusion of eliminating the need for threads (RTOS) altogether in many systems.</p> <p>fwiw&#8230;</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:24/comments/show#post-1803729</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:24/comments/show#post-1803729</link>
				<description></description>
				<pubDate>Tue, 25 Jun 2013 03:54:04 +0000</pubDate>
				<wikidot:authorName>martin_sustrik</wikidot:authorName>				<wikidot:authorUserId>939</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>Yes.</p> <p>The only thing different is that EVENTS have no EVENT prefix. I.e. NN_USOCK_CONNECTED rather than NN_USOCK_EVENT_CONNECTED. The reason is that outgoing events are the only entities visible to the user of the object &#8212; states and actions are private to the state machine. Thus, as the state machine API goes, EVENT prefix would serve no meaningful purpose and just make the identifiers longer.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:24/comments/show#post-1803578</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:24/comments/show#post-1803578</link>
				<description></description>
				<pubDate>Mon, 24 Jun 2013 21:53:51 +0000</pubDate>
				<wikidot:authorName>mike</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>I was looking over some of the new state machine code and wanted to make a clarification on the naming. Keep in mind I'm not a network programmer so these might not be the best examples.</p> <p>STATE:<br /> The internal state of the machine<br /> NN_USOCK_STATE_CONNECTED</p> <p>ACTION:<br /> A command placing the machine in a new state and possibly raising an event<br /> NN_USOCK_ACTION_CONNECT</p> <p>EVENT:<br /> Raised when the machine enters a new state<br /> NN_USOCK_EVENT_CONNECTED</p> <p>The distinction between ACTION and EVENT may or may not be necessary, I don't yet know enough about the internals and you might be just using STATE vs having an EVENT fire and event I believe is your up-stream function call.</p> <p>I hope this makes sense.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:24/comments/show#post-1803527</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:24/comments/show#post-1803527</link>
				<description></description>
				<pubDate>Mon, 24 Jun 2013 20:52:15 +0000</pubDate>
				<wikidot:authorName>mike</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>That makes sense, thanks for the clarification, looking forward to the state machine alpha.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:24/comments/show#post-1802015</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:24/comments/show#post-1802015</link>
				<description></description>
				<pubDate>Sat, 22 Jun 2013 08:08:04 +0000</pubDate>
				<wikidot:authorName>martin_sustrik</wikidot:authorName>				<wikidot:authorUserId>939</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <blockquote> <p>Can a source object ever have more than one owner?</p> </blockquote> <p>No. Not allowed.</p> <p>It's actually pretty crucial requirement. The idea is to have objects arranged in a tree (thus one owner for each one). Then we have to ways of communication:</p> <ol> <li>Up the tree (direction from root to leaves): this is implemented as simple function calls</li> <li>Down the tree (direction from leaves to root): this is implemented as state machine events</li> </ol> <p>That makes interactions between the components relatively easy to grasp. With mulitple owners (i.e. graph instead of tree) it would be much harder.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:24/comments/show#post-1802003</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:24/comments/show#post-1802003</link>
				<description></description>
				<pubDate>Sat, 22 Jun 2013 07:24:25 +0000</pubDate>
				<wikidot:authorName>martin_sustrik</wikidot:authorName>				<wikidot:authorUserId>939</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>Sure. But there's already a base class for all state machines (nn_fsm). Storing the integer there seems to be a cleaner solution.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:24/comments/show#post-1801980</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:24/comments/show#post-1801980</link>
				<description></description>
				<pubDate>Sat, 22 Jun 2013 06:12:43 +0000</pubDate>
				<wikidot:authorName>mike</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>Another option is to require all state machine objects to use a special allocator that over allocates allowing room for source_type and returns an offset pointer.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:24/comments/show#post-1801805</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:24/comments/show#post-1801805</link>
				<description></description>
				<pubDate>Fri, 21 Jun 2013 23:29:37 +0000</pubDate>
				<wikidot:authorName>mike</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>Four bytes seems reasonable due to alignment, you could even just use for example one byte if there would never be more than 255 types, or two bytes ect, and still have a couple free bytes for edge cases or anything else.</p> <p>I'm not familiar enough with the code base and how initialization works yet, so put another way, the requirement could be that the first four bytes of any object participating in the state machine belong to the owner so I think we are on the same page.</p> <p>Can a source object ever have more than one owner?</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:24/comments/show#post-1801789</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:24/comments/show#post-1801789</link>
				<description></description>
				<pubDate>Fri, 21 Jun 2013 22:55:17 +0000</pubDate>
				<wikidot:authorName>martin_sustrik</wikidot:authorName>				<wikidot:authorUserId>939</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>@mike: As for nn_cipc_handler_spic(…) I don;t like it for the same reason stated above: Having multiple handlers make code hard to follow (i.e. code belonging to a single state is suddenly scattered among different places in the source file.</p> <p>&quot;Reserving the few bytes&quot; thing seems more resonable. I thought of just reserving a single integer. You would initialise it when intialising the source and get it back once the source fires an event.</p> <p>For example:</p> <p>nn_timer_init (&amp;self-&gt;retry_timer, NN_REQ_RETRY_TIMER);</p> <p>And then, in the handler:</p> <p>if (source_type == NN_REQ_RETRY_TIMER &amp;&amp; event_type == NN_TIMER_TIMEOUT) {<br /> timer = (struct nn_timer*) source;<br /> &#8230;.<br /> }</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:24/comments/show#post-1801776</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:24/comments/show#post-1801776</link>
				<description></description>
				<pubDate>Fri, 21 Jun 2013 22:20:05 +0000</pubDate>
				<wikidot:authorName>martin_sustrik</wikidot:authorName>				<wikidot:authorUserId>939</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>@Ambroz: The reason is to keep the hierarchy of the handler this way: state=&gt;source=&gt;event_type.</p> <p>If you have different handler functions for different events the code will be structured (presumably) like this: event_type=&gt;source=&gt;state. That kind of code is extremely hard to follow.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:24/comments/show#post-1801486</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:24/comments/show#post-1801486</link>
				<description></description>
				<pubDate>Fri, 21 Jun 2013 15:27:06 +0000</pubDate>
				<wikidot:authorName>mike</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>Regarding adding source_type, without knowing more about the number of source_types and if they could be organized into groups based on behavior. Here are some thoughts&#8230;</p> <p>Reserve a few bytes at the beginning of the source object, the owner could then attach the type once before the state machine executes. This could also be used for other data such as the owner setting a flag on the source.</p> <p>Create a state machine for a single type in the O(n) cases and have the source call into the handler for that machine, for example nn_cipc_handler_spic(&#8230;). If possible it would be nice eliminate the need for &quot;if (source == &amp;cipc-&gt;sipc)&quot; without over complicating the state machine.</p> <p>If source_type cannot be avoided and the owner cannot write to the source object even one time during the wiring/initialization phase, consider some type of context object that the owner hands to the source that the source must pass with each handler call, that context object could contain the source_type, source_ptr etc.</p> <p>Reserving a few bytes in the source seems the most appealing, you could have an issue where a source object might have more than one owner, then you would have to consider how many owners a source object could have, but I could still see this being workable.</p> <p>If you can explain why some of these options won't work it might provide some more insight.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:24/comments/show#post-1801310</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:24/comments/show#post-1801310</link>
				<description></description>
				<pubDate>Fri, 21 Jun 2013 07:10:48 +0000</pubDate>
				<wikidot:authorName>Ambroz Bizjak</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>Martin, why does the concept of a FSM exist in your code at all? For examole, in cipc.c, you do nn_fsm_init_root and pass nn_cipc_handler to that, and by passing that to other init's you set up nn_cipc_handler to handle events from three different sources. Why not just have three callback functions, what benefit does this indirection provide?</p> <p>Even more, I would use different handlers for different event types, instead of using just one handler per event source. This way you can add event-specific arguments to the handler.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:24/comments/show#post-1800962</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:24/comments/show#post-1800962</link>
				<description></description>
				<pubDate>Thu, 20 Jun 2013 18:56:36 +0000</pubDate>
				<wikidot:authorName>martin_sustrik</wikidot:authorName>				<wikidot:authorUserId>939</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>Good suggestion about distinguishing the events and the actions. Currently, events have no specific prefix and actions have, confusingly, prefix _EVENT_. Let me fix that.</p> <p>As for handing of the control from cipc to sipc it's done here:</p> <p>nn_sipc_start (&amp;cipc-&gt;sipc, &amp;cipc-&gt;usock);</p> <p>What happens is that sipc object takes ownership of the usock object and redirects any events from it to itself. When the connection breaks, it hands ownership of the usock back to cipc object.</p> <p>One unrelated thought: I am considering passing adding one parameter to the handler function. Currently it is (target,source_ptr, event_type). I am thinking of extending it to (target, source_type, source_ptr, event_type). The problem it solves is when the state machine owns an unlimited number of source objects, for example, a list of sockets. In such case checking that source_ptr is one of the objects in the list would require list traversal (O(n) operation). Any thoughts about that?</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:24/comments/show#post-1800951</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:24/comments/show#post-1800951</link>
				<description></description>
				<pubDate>Thu, 20 Jun 2013 18:21:30 +0000</pubDate>
				<wikidot:authorName>mike</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>A source (usock) initiates an event (NN_USOCK_CONNECTED) on the target (cipc). The target state machine looks at the current state, looks at the source of the event and then acts on a valid event. target-&gt;state-&gt;source-&gt;event</p> <p>If this is correct you might consider a convention such as NN_USOCK_EVENT_CONNECTED, and it might even be useful distinguish between an action and event where an action ACTION_CONNECT is initiated and EVENT_CONNECTED moves the machine into STATE_CONNECTED, action and event would still reside at the same level in the state machine.</p> <div class="code"> <pre> <code> case NN_CIPC_STATE_CONNECTING: if (source == &amp;cipc-&gt;usock) { switch (type) { case NN_USOCK_CONNECTED: nn_sipc_start (&amp;cipc-&gt;sipc, &amp;cipc-&gt;usock); cipc-&gt;state = NN_CIPC_STATE_ACTIVE; return; case NN_USOCK_ERROR: nn_usock_stop (&amp;cipc-&gt;usock); cipc-&gt;state = NN_CIPC_STATE_STOPPING_USOCK; return; default: nn_assert (0); } } nn_assert (0);</code> </pre></div> <p>Regarding the nested state machines:</p> <blockquote> <p>For example, when cipc state machine is in ACTIVE state it hands the execution to sipc sub-state-machine.</p> </blockquote> <p>I could not find the hand off in cipc.cs NN_CIPC_STATE_ACTIVE, can you point me to src?</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:24/comments/show#post-1800832</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:24/comments/show#post-1800832</link>
				<description></description>
				<pubDate>Thu, 20 Jun 2013 15:49:13 +0000</pubDate>
				<wikidot:authorName>martin_sustrik</wikidot:authorName>				<wikidot:authorUserId>939</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>Several good points here. Let me comment on them one by one.</p> <p>I don't feel good about name 'type' myself. It's not another state. It's the type of the event being processed. So, a single source object can emit different kind of events, say a socket can emit SENT and RECEIVED events. 'type' argument is used to distinguish between the two. Suggestions for better fitting name are welcome.</p> <p>As for state transition tables I have deliberately not used them. The rationale is the same as the rationale for not using code generation: State transitions tables make the code very hard to follow. Instead, I've opted for a single transition function with three nested levels of switches (in this order): the state, the source of the event, the type of the event. That makes it relatively easy to find your way through the state machine be simply scrolling the source code up and down.</p> <p>As for nested state machines, I actually use them. For example, when cipc state machine is in ACTIVE state it handles the execution to sipc sub-state-machine. When sipc state machine terminates it hands the execution back to the cipc state machine. The same trick can be applied recursively, getting an arbitrary stack depth.</p> <p>The debug log is a pretty neat idea. It would be worth of implementing, I guess.</p> <p>Great to hear you don't see any barrier to entry. That's what I was trying to achieve. Typically, when code generation or macros are used, people feel there's an barrier to overcome.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:24/comments/show#post-1800763</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:24/comments/show#post-1800763</link>
				<description></description>
				<pubDate>Thu, 20 Jun 2013 13:29:19 +0000</pubDate>
				<wikidot:authorName>mike</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>I took a look at the state machine in cipc.c on the aio2 branch it's very clean and easy to understand the transitions. I prefer the boilerplate to code-gen or macros any day.</p> <p>One thing I did find a little confusing was the nested &quot;switch (type)&quot; it looks like type is the state of another state machine, &quot;switch (sock-&gt;state)&quot;.</p> <p>There is also the possibility of using a state transition table and/or function lookup tables to remove some of the boiler plate. With this approach your default: handles all the common cases, like make a call and sets the next state and more complex cases get their own case statement &quot;case NN_COMPLICATED_STATE:&quot;. If you can make the lookup arrays easy to read and maintain this could be a win. You could even case the boilerplate states and let them all fall through to the boilerplate lookup-&gt;call-&gt;set case and still maintain the default state for trapping invalid states. Lookup tables can also eliminate a lot of branching.</p> <p>In even more complex state transitions a stack can be used to pass information between nested states, not sure that applies here, but it's useful in lex/parse.</p> <p>Another nice advantage to the state machine approach is debugging, just log the states or even keep the last n states in a ring buffer.</p> <p>I don't see any barrier to entry here, all the states and transitions are clearly defined in a hundred lines of very readable code. If you need any clarification, email or reply. I've have built quite a few DFSMs.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:24/comments/show#post-1800376</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:24/comments/show#post-1800376</link>
				<description></description>
				<pubDate>Wed, 19 Jun 2013 19:32:43 +0000</pubDate>
				<wikidot:authorName>martin_sustrik</wikidot:authorName>				<wikidot:authorUserId>939</wikidot:authorUserId>				<content:encoded>
					<![CDATA[
						 <p>I've already written it by hand &#8212; i.e. no code generation.</p> <p>Although it means a lot of boilerplate code in the codebase (yuck!), on the other hand it allows any developer to peek directly at the source code and understand what's going on without to learn a new language.</p> 
				 	]]>
				</content:encoded>							</item>
					<item>
				<guid>http://250bpm.com/blog:24/comments/show#post-1800112</guid>
				<title>(no title)</title>
				<link>http://250bpm.com/blog:24/comments/show#post-1800112</link>
				<description></description>
				<pubDate>Wed, 19 Jun 2013 15:05:12 +0000</pubDate>
				<wikidot:authorName>mike</wikidot:authorName>								<content:encoded>
					<![CDATA[
						 <p>Perhaps part of the barrier to entry with OpenAMQ was the XML/C DSL and code generation it uses, not sure at what version this started, but it looks like it's always used a DSL+CodeGenerator, possibly Libero.</p> <p>Are you considering a code generator for nanomsg or a spec/api for the state machine?</p> 
				 	]]>
				</content:encoded>							</item>
				</channel>
</rss>