Documented the dispatch functions. Actually there will be two entries left
[rodin/chimara.git] / libchimara / dispatch.c
index b1f84dacd6d40c6937460961e6e394df30a69b5e..895d2e7e4c249dd16e1e6e36489591856f4e84c0 100644 (file)
@@ -6,6 +6,66 @@
 
 extern GPrivate *glk_data_key;
 
+/**
+ * gidispatch_set_object_registry:
+ * @regi: Function to call whenever an opaque object is created.
+ * @unregi: Function to call whenever an opaque object is destroyed.
+ *
+ * The Glk API refers to opaque objects by pointer; but a VM probably cannot 
+ * store pointers to native memory. Therefore, a VM program will want to keep a
+ * VM-accessible collection of opaque objects.
+ * 
+ * <note><para>
+ *   For example, it might keep a hash table for each opaque object class,
+ *   mapping integer identifiers to object pointers.
+ * </para></note>
+ * 
+ * To make this possible, a Glk library must implement 
+ * gidispatch_set_object_registry().
+ * 
+ * Your program calls gidispatch_set_object_registry() early (before it begins
+ * actually executing VM code.) You pass in two function pointers, matching the
+ * following prototypes:
+ * |[
+ * #gidispatch_rock_t my_vm_reg_object(void *obj, #glui32 objclass);
+ * void my_vm_unreg_object(void *obj, #glui32 objclass, #gidispatch_rock_t objrock);
+ * ]|
+ * 
+ * Whenever the Glk library creates an object, it will call my_vm_reg_object(). 
+ * It will pass the object pointer and the class number (from 0 to
+ * <inlineequation><mathphrase>N - 1</mathphrase><alt>N - 
+ * 1</alt></inlineequation>, where N is the value returned by
+ * gidispatch_count_classes().)
+ * 
+ * You can return any value in the #gidispatch_rock_t object; the library will
+ * stash this away inside the object.
+ * 
+ * <note><para>
+ *   Note that this is entirely separate from the regular Glk rock, which is
+ *   always a #glui32 and can be set independently.
+ * </para></note>
+ * 
+ * Whenever the Glk library destroys an object, it will call
+ * my_vm_unreg_object(). It passes you the object pointer, class number, and the
+ * object rock.
+ *
+ * One significant detail: It is possible that some Glk objects will already
+ * exist when your glk_main() function is called.
+ * 
+ * <note><para>
+ *   For example, MacGlk can open a stream when the user double-clicks a file;
+ *   this occurs before glk_main().
+ * </para></note>
+ * 
+ * So when you call gidispatch_set_object_registry(), it may immediately call
+ * your my_vm_reg_object() callback, notifying you of the existing objects. You
+ * must be prepared for this possibility.
+ * 
+ * <note><para>
+ *   If you are keeping hash tables, for example, create them before you call
+ *   gidispatch_set_object_registry().
+ * </para></note>
+ */
 void 
 gidispatch_set_object_registry(gidispatch_rock_t (*regi)(void *obj, glui32 objclass), void (*unregi)(void *obj, glui32 objclass, gidispatch_rock_t objrock))
 {
@@ -29,9 +89,26 @@ gidispatch_set_object_registry(gidispatch_rock_t (*regi)(void *obj, glui32 objcl
     }
 }
 
+/**
+ * gidispatch_get_objrock:
+ * @obj: An opaque object.
+ * @objclass: One of #gidisp_Class_Window, #gidisp_Class_Stream,
+ * #gidisp_Class_Fileref, or #gidisp_Class_Schannel.
+ *
+ * You can, at any time, get the object rock of an object. The library
+ * implements this function.
+ * 
+ * With this and your two callbacks, you can maintain (say) a hash table for
+ * each object class, and easily convert back and forth between hash table keys
+ * and Glk object pointers. A more sophisticated run-time system (such as Java)
+ * could create a typed VM object for every Glk object, thus allowing VM code to
+ * manipulate Glk objects intelligently.
+ */
 gidispatch_rock_t 
 gidispatch_get_objrock(void *obj, glui32 objclass)
 {
+       g_return_val_if_fail(obj, NULL);
+       
        switch(objclass) 
        {
                case gidisp_Class_Window:
@@ -49,6 +126,61 @@ gidispatch_get_objrock(void *obj, glui32 objclass)
        }
 }
 
+/**
+ * gidispatch_set_retained_registry:
+ * @regi: Function to call whenever the Glk library assumes ownership of an
+ * array.
+ * @unregi: Function to call whenever the Glk library releases ownership of an
+ * array.
+ *
+ * A few Glk functions take an array and hold onto it. The memory is 
+ * <quote>owned</quote> by the library until some future Glk call releases it.
+ * While the library retains the array, your program should not read, write,
+ * move, or deallocate it. When the library releases it, the contents are in
+ * their final form, and you can copy them out (if appropriate) and dispose of
+ * the memory as you wish.
+ * 
+ * To allow this, the library implements gidispatch_set_retained_registry().
+ * 
+ * Again, you pass in two function pointers:
+ * |[
+ * #gidispatch_rock_t my_vm_reg_array(void *array, #glui32 len, char *typecode);
+ * void my_vm_unreg_array(void *array, #glui32 len, char *typecode, #gidispatch_rock_t objrock);
+ * ]|
+ *
+ * Whenever a Glk function retains an array, it will call my_vm_reg_array().
+ * This occurs only if you pass an array to an argument with the
+ * <code>"#!"</code> prefix.
+ *
+ * <note><para>
+ *   But not in every such case. Wait for the my_vm_reg_array() call to confirm
+ *   it.
+ * </para></note>
+ *
+ * The library passes the array and its length, exactly as you put them in the
+ * #gluniversal_t array. It also passes the string which describes the argument.
+ *
+ * <note><para>
+ *   Currently, the only calls that retain arrays are glk_request_line_event(),
+ *   glk_stream_open_memory(), glk_request_line_event_uni(), and
+ *   glk_stream_open_memory_uni(). The first two of these use arrays of
+ *   characters, so the string is <code>"&+#!Cn"</code>. The latter two use
+ *   arrays of #glui32, so the string is <code>"&+#!Iu"</code>.
+ * </para></note>
+ * 
+ * You can return any value in the #gidispatch_rock_t object; the library will
+ * stash this away with the array.
+ * 
+ * When a Glk function releases a retained array, it will call
+ * my_vm_unreg_array(). It passes back the same @array, @len, and @typecode
+ * parameters, as well as the #gidispatch_rock_t you returned from
+ * my_vm_reg_array().
+ * 
+ * With these callbacks, you can maintain a collection of retained arrays. You
+ * can use this to copy data from C arrays to your own data structures, or keep
+ * relocatable memory locked, or prevent a garbage-collection system from
+ * deallocating an array while Glk is writing to it.
+ */
 void 
 gidispatch_set_retained_registry(gidispatch_rock_t (*regi)(void *array, glui32 len, char *typecode), void (*unregi)(void *array, glui32 len, char *typecode, gidispatch_rock_t objrock))
 {