![]() |
License / Documentation home / Help and feedback | ![]() |
Let's say you want to write a frame to the Hub, but you don't want to do
it from a dispatch function. You need an environment to use, so you save a
reference to the environment from within a dispatch function. But later, when
you try to write your frame, your application crashes. What went wrong? The
answer lies in the memory management rules for environment objects, which
is the topic of this section.
Gal_Frame do_something(Gal_Frame f, void *server_data)
{
GalSS_Environment *env = (GalSS_Environment *) server_data;
Gal_Frame new_f;
/* ... */
GalSS_EnvWriteFrame(env, new_f, 0);
/* ... */
}
(We talk about this in more detail in the documentation
on adding a server.) These call environments can be used inside dispatch
functions to provide
replies or send new
messages to the Hub. But dispatch functions aren't restricted to providing
a reply to an incoming message or sending new messages; they can also set
up callbacks or timed tasks which may send new messages later. So the programmer
might want to save away a call environment to send a message outside the
scope of the dispatch function. However, if you're not careful, you can crash
your program doing this. The reason is that the call environment is allocated
for the call to the dispatch function, and freed (under normal circumstances)
when the dispatch function exits. So if you touch it later, it'll be gone.
In order to address this issue, we've set up the call environment so that
it's managed by a reference count. When the reference count reaches
0, the call environment is freed. As a programmer, there are a number of ways
you can exploit this feature to ensure that the environment will be around
when you need it.
There are a number of circumstances where you might logically want to save
away a call environment. These include broker callbacks and timed tasks. In
order to make your job easier, we provide utilities for cleanly saving a
call environment in all the callback contexts the infrastructure supports.
In particular, the Galaxy Communicator library provides environment-aware broker callback and timed task setup, as well as a way of maintaining an environment through successive calls to dispatch functions. In this section, we describe some of these functions.
void GalSS_TaskSetEnvironment(Gal_TaskPkg
*p, GalSS_Environment *env)
Sets the environment associated with the task p to env.
GalSS_Environment *GalSS_TaskGetEnvironment(Gal_TaskPkg
*p)
Returns the environment associated with the task p.
Gal_TaskPkg *GalSS_EnvAddTask(GalSS_Environment
*env, void (*task)(Gal_TaskPkg *), void *caller_data,
long num_millisecs, int read_blocking_available, GAL_SOCKET
*read_socket, GAL_SOCKET *write_socket, GAL_SOCKET *err_socket,
FILE *read_file, FILE *write_file, FILE*err_file,
Gal_TaskConditionFn condition, void (*cleanup_fn)(void *))
This function provides all the functionality of Gal_AddTaskExtended, but
also saves away the call environment env for access using the function
GalSS_TaskGetEnvironment. A task thus established can be refired in any of
the normal ways; see the timed task documentation
for details.
At times, connections may be associated with UI elements, which can issue new messages. So the UI itself is an element outside the scope of dispatch functions where it would be helpful to have a call environment to use to issue new messages. It's not enough to set up the environment when the connection is established; crucial properties of the UI interaction, such as the session ID, may be changed by other servers in the course of evaluation. The safest thing to do is to create an environment for the UI when the connection is established, update it every time a dispatch function is called, and free the environment when the connection is shut down. The function GalSS_EnvMaintainInLocation does this for you.
void GalSS_EnvMaintainInLocation(GalIO_CommStruct
*gcomm, const char *initial_session_id, GalSS_Environment
**env_loc)
The connection gcomm is the connection to the Hub which is associated
with a UI element for the current session, and hosts the dispatch functions
which are fired. This function seeds the location env_loc with a new
environment and updates its session ID to initial_session_id. It
sets a dispatch function callback via GalIO_AddConnectionDispatchFnCallback
to keep the location current, and sets up a shutdown callback to free
the environment.
void GalSS_EnvLock(GalSS_Environment
*env)
Increments the reference counter on the environment env to indicate
that it should not be freed.
void GalSS_EnvUnlock(GalSS_Environment
*env)
Decrements the reference counter on the environment env. When the
reference counter reaches 0, the environment is freed.
GalSS_Environment *GalSS_EnvCopy(GalSS_Environment
*old_env)
Copies the environment old_env and sets the reference counter in
the new environment to 1.
GalSS_Environment *GalSS_EnvCopyNoLock(GalSS_Environment
*old_env)
Copies the environment old_env. The reference counter in the new
environment remains at 0. This function is present mostly for internal backward
compatibility.
GalSS_Environment *GalSS_EnvCreate(GalIO_CommStruct
*gcomm)
Creates an environment from the connection gcomm.
int GalSS_EnvReturnRequired(GalSS_Environment
*env)
Returns 1 if the call environment represents a dispatch function invocation
for which a return is expected, or 0 if it does not.
![]() |
License / Documentation home / Help and feedback | ![]() |