Self help (3) ...



	Yet more haphazard mental meandering.

* Contents:
	. picking a variable name
	. CORBA & re-enterancy
	. good taste
	. setjmp / longjmp


* Picking a variable name

	Whilst clearly it is possible to pick a random variable name
for any particular variable - it has been discovered, that choosing a
common variable name per type can be most helpful, especialy in large
complex classes.

	By this I mean, that instead of having:

static void my_virtual_method (FooBar *goat);
static void my_signal_handler (FooBar *cow);
void        my_public_method  (FooBar *sheep);

	That by sticking to (the more staid and less self expresive):

static void my_virtual_method (FooBar *foo_bar);
static void my_signal_handler (FooBar *foo_bar);
void        my_public_method  (FooBar *foo_bar);

	one can move code around in this module with total impunity,
without having to repeatedly s/cow/sheep/ etc. This also works well
as a scheme across modules - and can make common types quite visible.

	Clearly the '_' mangling is not neccessary, here *fb would
probably be quite adequate as long as it is unique enough.


* CORBA & re-enterancy

	One of the most fun things about CORBA is the possibility of
re-enterancy - whilst people moan constantly about this, it is in fact
neccessary for even the most basic of operations. Essentialy what it
means is this:

	When you as a client, invoke a CORBA method on an object, as
soon as you hit the ORB - it is possible for an incoming CORBA request
to be serviced. [1]. What this means is that if you have code like
this:

	for (l = priv->list; l; l = l->next)
		bonobo_object_release_unref (l->data, NULL);
	g_slist_free (priv->list);

	Then you quite possibly have a bug. This is due to the fact
that a _release_unref performs a Bonobo_Unknown_unref[2] on a remote
Bonobo object - and inbetween that unref returning, and the next
element of the list being processed - it is entirely possible that the
above loop has been re-entered and the list is now empty - leaving
you with a pointer to floating memory.

	Of course, innumerable similar less obvious re-enterancies can
occur - be warned, and vigilant.


* Good Taste

	Code should be beautiful, it should make the eye flow over it
soothingly - highlighting structure and pertainant features, and
making the life of the maintainer pleasurable.

	One way to achieve this is with nice alignment, this applies
to all manner of things, particularly function prototypes and
arguments, but also to the humble structure.

	Consider:

typedef struct {
	char *name;
	unsigned int frobnicate:1;
} MyStruct;

	It is evil to look at, and unhelpful. It is far better to
align the types and members in columns, and this is where the 'guint'
type is actualy useful:

typedef struct {
	char  *name;
	guint  frobnicate : 1;
} MyStruct;

	Note some things:

		+ pointer type's type info is split over the column,
		ie. we have char  *foo, not char* foo or char * foo.

		+ consequently alignment happens on member name,
		disregarding the '*' prefix [ which is part of the
		type ]

		+ NB. the unsigned-ness of 'frobnicate' is nice,
		since it's truth values are then 1 and 0 instead of
		0 and -1.


* setjmp / longjmp

	Firstly the caveat from the man page:

		setjmp() and sigsetjmp make programs hard to
		understand and maintain.  If possible an alternative
		should be used.

	However, there are places where setjmp, and sigsetjmp are
particularly useful - quite where these are is really up to your state
of mind. Sometimes they are useful in deeply recursive routines, where
error recovery can be particuarly painful and impose a large overhead.
Other times, they are the ultimate combat coding weapon - in
conjunction with a tastefuly camoflagued SIGSEGV.

	Either way, setjmp / longjmp are both _extremely_ fast and
very simple. Setjmp stores the position of the stack and instruction
pointers ( as well as some registers ) in a 'jmp_buf' environment.
When it is first called, it returns 0, but when hit from a longjmp, it
returns the value passed by the longjmp.

int
foo (void)
{
	jmp_buf ptr;
	int     i, jmp;

	switch (setjmp (ptr)) {
		case 0:
			i = 0;
		case 1:
			jmp = 3;
			i++;
			break;
		case 3:
			jmp = i < 2 ? 0 : 4;
			break;
		case 4:
			return i;
	}
	longjmp (ptr, jmp);
}

	So, congratulations to those who can see instantly what number
this will return [3]


* Conclusions

	Name variables consistantly, think carefuly about
re-enterancy, especialy when calling methods that don't look as if
they do CORBA work. Make your code beautiful to read - and while
you're going you'll discover bugs and don't use setjmp / longjmp
unless you have to.


* Next issue

	Any pet peeves I come across in my wandering, tips on writing
CORBA code so it ports easily to Gnome 2.0 and general gotchas in
porting widgets to Gtk+ 2.0.


[1] - while this is not in fact true for oneway or in-proc methods,
it's worth bearing in mind always.

[2] - some would argue ( compellingly in fact ) that unref should be
oneway, indeed if someone wants to suggest it on gcl - go for it,
UNO's acquire & release are both 'oneway', but having both aquire and
release oneway seems intuitively somewhat risky to me for some reason.

[3] - Answer : the even prime, despite case 3: seeming to jump to case
0: causing an infinite loop, setjmp only returns 0 the first time, and
1 if a 0 is passed via longjmp.

-- 
 mmeeks gnu org  <><, Pseudo Engineer, itinerant idiot





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]