     [file version.texi not included]

Copyright © 2005 Don Owens

This code is released under the BSD license:

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

* Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

This manual describes the external interface to libcfu version VERSION

Copyright © 2005 Don Owens All rights reserved.

This code is released under the BSD license:

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

* Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

This manual describes the interface to libcfu version VERSION

Copyright © 2005 Don Owens

Data structures
***************

Hash table
==========

 -- Special Form: typedef u_int32_t (*cfuhash_function_t)(const void * KEY, size_t LENGTH)
     Prototype for a pointer to a hashing function.

 -- Special Form: typedef void (*cfuhash_free_fn_t)(void * DATA)
     Prototype for a pointer to a free function.

 -- Special Form: typedef int (*cfuhash_remove_fn_t)(void * KEY, size_t KEY_SIZE, void * DATA, size_t DATA_SIZE, void * ARG)
     Prototype for a pointer to a function that determines whether or not to remove an entry from the hash.

 -- Special Form: typedef int (*cfuhash_foreach_fn_t)(void * KEY, size_t KEY_SIZE, void * DATA, size_t DATA_SIZE, void * ARG)
     Prototype for a pointer to a function to be called foreach key/value pair in the hash by cfuhash_foreach().  The return value should normally be zero.  A non-zero return value means to stop iterating over the key/value pairs.

 -- Function: cfuhash_table_t * cfuhash_new (size_t SIZE, u_int32_t FLAGS)

     Creates a new hash table.

 -- Function: cfuhash_table_t * cfuhash_new_with_initial_size (size_t SIZE)

     Creates a new hash table with the specified size (number of buckets).

 -- Function: cfuhash_table_t * cfuhash_new_with_flags (u_int32_t FLAGS)

     Creates a new hash table with the specified flags.  Pass zero for flags if you want the defaults.

 -- Function: cfuhash_table_t * cfuhash_new_with_free_fn (size_t SIZE, u_int32_t FLAGS, cfuhash_free_fn_t FF)

     Same as cfuhash_new() except automatically calls cfuhash_set_free_fn().

 -- Function: int cfuhash_copy (cfuhash_table_t * SRC, cfuhash_table_t * DST)

     Copies entries in src to dst

 -- Function: cfuhash_table_t * cfuhash_merge (cfuhash_table_t * HT1, cfuhash_table_t * HT2, u_int32_t FLAGS)

     Returns a new hash containing entries from both hash tables. For any entries with the same key, the one from ht2 wins.

 -- Function: int cfuhash_set_hash_function (cfuhash_table_t * HT, cfuhash_function_t HF)

     Sets the hashing function to use when computing which bucket to add entries to.  It should return a 32-bit unsigned integer.  By default, Perl's hashing algorithm is used.

 -- Function: int cfuhash_set_thresholds (cfuhash_table_t * HT, float LOW, float HIGH)

     Sets the thresholds for when to rehash.  The ratio num_entries/buckets is compared against low and high.  If it is below 'low' or above 'high', the hash will shrink or grow, respectively, unless the flags say to do otherwise.

 -- Function: int cfuhash_set_free_function (cfuhash_table_t * HT, cfuhash_free_fn_t FF)

     Sets the function to use when removing an entry from the hash, i.e., when replacing an existing entry, deleting an entry, or clearing the hash.  It is passed the value of the entry as a void *.

 -- Function: u_int32_t cfuhash_get_flags (cfuhash_table_t * HT)

     Returns the hash's flags. See below for flag definitions.

 -- Function: u_int32_t cfuhash_set_flag (cfuhash_table_t * HT, u_int32_t FLAG)

     Sets a flag.

 -- Function: u_int32_t cfuhash_clear_flag (cfuhash_table_t * HT, u_int32_t NEW_FLAG)

     Clears a flag.

 -- Function: int cfuhash_get_data (cfuhash_table_t * HT, const void * KEY, size_t KEY_SIZE, void ** DATA, size_t * DATA_SIZE)

     Returns the value for the entry with given key.  If key_size is -1, key is assumed to be a null-terminated string.  If data_size is not NULL, the size of the value is placed into data_size.

 -- Function: int cfuhash_exists_data (cfuhash_table_t * HT, const void * KEY, size_t KEY_SIZE)

     Returns 1 if an entry with the given key exists in the hash, 0 otherwise.

 -- Function: int cfuhash_put_data (cfuhash_table_t * HT, const void * KEY, size_t KEY_SIZE, void * DATA, size_t DATA_SIZE, void ** R)

     Inserts the given data value into the hash and associates it with key.  If key_size is -1, key is assumed to be a null-terminated string.  If data_size is -1, it is assumed to be a null-terminated string (it's length will be calculated using strlen).  If data_size is zero, it will be returned as zero when the value is requested.

 -- Function: void cfuhash_clear (cfuhash_table_t * HT)

     Clears the hash table (deletes all entries).

 -- Function: void * cfuhash_delete_data (cfuhash_table_t * HT, const void * KEY, size_t KEY_SIZE)

     Deletes the entry in the hash associated with key. If the entry existed, it's value will be returned.

 -- Function: void **cfuhash_keys_data (cfuhash_table_t * HT, size_t * NUM_KEYS, size_t ** KEY_SIZES, int FAST)

     Returns all the keys from the hash.  The number of keys is placed into the value pointed to by num_keys.  If key_sizes is not NULL, it will be set to an array of key sizes.  If fast is zero, copies of the keys are returned.  Otherwise, pointers to the real keys will be returned.

 -- Function: int cfuhash_each_data (cfuhash_table_t * HT, void ** KEY, size_t * KEY_SIZE, void ** DATA, size_t * DATA_SIZE)

     Initializes a loop over all the key/value pairs in the hash.  It returns the first key/value pair (see cfuhash_next_data()).  1 is returned if there are any entries in the hash.  0 is returned otherwise.

 -- Function: int cfuhash_next_data (cfuhash_table_t * HT, void ** KEY, size_t * KEY_SIZE, void ** DATA, size_t * DATA_SIZE)

     Gets the next key/value pair from the hash.  You must initialize the loop using cfuhash_each_data() before calling this function. If a entry is left to return, 1 is returned from the function.  0 is returned if there are no more entries in the hash.

 -- Function: size_t cfuhash_foreach_remove (cfuhash_table_t * HT, cfuhash_remove_fn_t R_FN, cfuhash_free_fn_t FF, void * ARG)

     Iterates over the key/value pairs in the hash, passing each one to r_fn, and removes all entries for which r_fn returns true. If ff is not NULL, it is the passed the data to be freed.  arg is passed to r_fn.

 -- Function: size_t cfuhash_foreach (cfuhash_table_t * HT, cfuhash_foreach_fn_t FE_FN, void * ARG)

     Iterates over the key/value pairs in the hash, passing each one to fe_fn, along with arg. This locks the hash, so do not call any operations on the hash from within fe_fn unless you really know what you're doing.

     If the return value from fe_fn() is not zero, the iteration stops.

 -- Function: int cfuhash_destroy (cfuhash_table_t * HT)

     Frees all resources allocated by the hash.

 -- Function: int cfuhash_destroy_with_free_fn (cfuhash_table_t * HT, cfuhash_free_fn_t FF)

     Frees all resources allocated by the hash.  If ff is not NULL, it is called for each hash entry with the value of the entry passed as its only argument.  If ff is not NULL, it overrides any function set previously with cfuhash_set_free_function().

 -- Function: int cfuhash_rehash (cfuhash_table_t * HT)

     Rebuild the hash to better accomodate the number of entries. See cfuhash_set_thresholds().

 -- Function: size_t cfuhash_num_entries (cfuhash_table_t * HT)

     Returns the number entries in the hash.

 -- Function: size_t cfuhash_num_buckets (cfuhash_table_t * HT)

     Returns the number of buckets allocated for the hash.

 -- Function: size_t cfuhash_num_buckets_used (cfuhash_table_t * HT)

     Returns the number of buckets actually used out of the total number allocated for the hash.

 -- Function: char * cfuhash_bencode_strings (cfuhash_table_t * HT)

     Assumes all the keys and values are null-terminated strings and returns a bencoded string representing the hash (see http://www.bittorrent.com/protocol.html)

 -- Function: int cfuhash_lock (cfuhash_table_t * HT)

     Locks the hash.  Use this with the each and next functions for concurrency control.  Note that the hash is locked automatically when doing inserts and deletes, so if you lock the hash and then try to insert something into it, you may get into a deadlock, depending on your system defaults for how mutexes work.

 -- Function: int cfuhash_unlock (cfuhash_table_t * HT)

     Unlocks the hash.  Use this with the each an next functions for concurrency control.  The caveat for cfuhash_lock() also applies to this function.

 -- Function: int cfuhash_pretty_print (cfuhash_table_t * HT, FILE * FP)

     Pretty print the hash's key/value pairs to the stream fp.  It is assumed that all the keys and values are null-terminated strings.

These are like the _data versions of these functions, with the following exceptions:

1) They assume that the key provided is a null-terminated string.

2) They don't worry about the size of the data.

3) Returned keys or values are the return value of the function.

 -- Function: void * cfuhash_get (cfuhash_table_t * HT, const char * KEY)

 -- Function: int cfuhash_exists (cfuhash_table_t * HT, const char * KEY);

 -- Function: void * cfuhash_put (cfuhash_table_t * HT, const char * KEY, void * DATA);

 -- Function: void * cfuhash_delete (cfuhash_table_t * HT, const char * KEY);

 -- Function: int cfuhash_each (cfuhash_table_t * HT, char ** KEY, void ** DATA);

 -- Function: int cfuhash_next (cfuhash_table_t * HT, char ** KEY, void ** DATA);

 -- Function: void ** cfuhash_keys (cfuhash_table_t * HT, size_t * NUM_KEYS, int FAST);

Valid flags for cfuhash_new() or cfuhash_set_flag):

 -- CFUHASH_NOCOPY_KEYS:
     Don't copy the key when adding an entry to the hash table.

 -- CFUHASH_NO_LOCKING:
     Don't not use any mutexes.  Beware that this flag makes the hash table non thread-safe.

 -- CFUHASH_FROZEN:
     Do not rehash (don't grow or shrink the number of buckets in the hash table when the thresholds are reached).

 -- CFUHASH_FROZEN_UNTIL_GROWS:
     Do not rehash until the upper threshold is reached the first time (useful for preallocating a large hash to avoid rehashing while filling it).

 -- CFUHASH_FREE_DATA:
     Call free() on the values when cfuhash_destroy() is called.

 -- CFUHASH_IGNORE_CASE:
     Treat the keys case-insensitively.

Linked list
===========

 -- Special Form: typedef int (*cfulist_foreach_fn_t)(void * DATA, size_t DATA_SIZE, void * ARG)
     Function called for each element in the list when passed to cfulist_foreach().  A non-zero return value means to stop iteration.

 -- Special Form: typedef void * (*cfulist_map_fn_t)(void *DATA, size_t DATA_SIZE, void *ARG, size_t *NEW_DATA_SIZE)
     Function called for each element in the list when passed to cfulist_map().  The return value is used to build a new list.

 -- Special Form: typedef void (*cfulist_free_fn_t)(void * DATA)
     Function called to free the data in an element.

 -- Function: cfulist_t * cfulist_new ();

     Returns a new list.

 -- Function: size_t cfulist_num_entries (cfulist_t *LIST)

     Returns the number of entries in the list.

 -- Function: int cfulist_push_data (cfulist_t * LIST, void * DATA, size_t DATA_SIZE)

     Push a value onto the end of the list.

 -- Function: int cfulist_pop_data (cfulist_t * LIST, void ** DATA, size_t * DATA_SIZE)

     Pop a value from the end of the list (removing it from the list).

 -- Function: int cfulist_unshift_data (cfulist_t * LIST, void * DATA, size_t DATA_SIZE)

     Add a value at the beginning of the list.

 -- Function: int cfulist_shift_data (cfulist_t * LIST, void ** DATA, size_t * DATA_SIZE)

     Shift a value off the beginning of the list.

 -- Function: int cfulist_enqueue_data (cfulist_t * LIST, void * DATA, size_t DATA_SIZE)

     Add a value at the end of the queue (equivalent to push)

 -- Function: int cfulist_dequeue_data (cfulist_t * LIST, void ** DATA, size_t * DATA_SIZE)

     Remove the value at the beginning of the list (equivalent to shift).

 -- Function: int cfulist_first_data (cfulist_t * LIST, void ** DATA, size_t * DATA_SIZE);

     Return the first entry from the list (without removing it from the list).

 -- Function: int cfulist_last_data (cfulist_t * LIST, void ** DATA, size_t * DATA_SIZE);

     Return the last entry from the list (without removing it from the list).

 -- Function: int cfulist_nth_data (cfulist_t * LIST, void ** DATA, size_t * DATA_SIZE, size_t N);

     Return the nth entry from the list (without removing it from the list).  n starts at zero.

 -- Function: void cfulist_reset_each (cfulist_t * LIST);

 -- Function: int cfulist_each_data (cfulist_t * LIST, void ** DATA, size_t * DATA_SIZE);

 -- Function: int cfulist_next_data (cfulist_t * LIST, void ** DATA, size_t * DATA_SIZE);

 -- Function: size_t cfulist_foreach (cfulist_t * LIST, cfulist_foreach_fn_t FE_FN, void * ARG);

     Calls fe_fn() for each element in the list. Also passes arg on each call.  Do not try to manipulate the list inside fe_fn(), as the list will be locked.

     If fe_fn() returns a non-zero value, the iteration over the elements stops.

 -- Function: cfulist_t *cfulist_map (cfulist_t *LIST, cfulist_map_fn_t MAP_FN, void *ARG);
     Creates a new list from the list passed in.  Calls map_fn() on each element in the list.  The return value is placed in the corresponding position in the new list.

 -- Function: void cfulist_destroy (cfulist_t * LIST)

     Free all resources used by the list.

 -- Function: void cfulist_destroy (cfulist_t * LIST, cfulist_free_fn_t FREE_FN)

     Free all resources used by the list. If free_fn is not NULL, call it for each element of the list, passing the data to it as a void *.

When you don't care about the size of the data

 -- Function: int cfulist_push (cfulist_t * LIST, void * DATA)

 -- Function: void * cfulist_pop (cfulist_t * LIST);

 -- Function: int cfulist_unshift (cfulist_t * LIST, void * DATA);

 -- Function: void * cfulist_shift (cfulist_t * LIST);

 -- Function: int cfulist_enqueue (cfulist_t * IST, void * DATA);

 -- Function: void * cfulist_dequeue (cfulist_t * LIST);

Strings -- assume data is a null-terminated string -- size is calculated by strlen(data) + 1

 -- Function: int cfulist_push_string (cfulist_t * LIST, char * DATA)

 -- Function: char * cfulist_pop_string (cfulist_t * LIST);

 -- Function: int cfulist_unshift_string (cfulist_t * LIST, char * DATA);

 -- Function: char * cfulist_shift_string (cfulist_t * LIST);

 -- Function: int cfulist_enqueue_string (cfulist_t * LIST, char * DATA);

 -- Function: char * cfulist_dequeue_string (cfulist_t * LIST);

 -- Function: char * cfulist_join (cfulist_t * LIST, const char * DELIMITER)

Strings
=======

 -- Function: cfustring_t * cfustring_new (size_t INITIAL_SIZE)

     Returns a new String.

 -- Function: cfustring_t * cfustring_new_from_string (const char * STRING)

     Returns a new String initalized with the given string.

 -- Function: int cfustring_dup (cfustring_t * CFU_STR, const char * STRING)

     Overwrite anything currently in cfu_str with string.

 -- Function: int cfustring_clear (cfustring_t * CFU_STR)

     Truncate the string.

 -- Function: int cfustring_append (cfustring_t * CFU_STR, const char * STR)

     Append str to the end of the buffer in cfu_str.

 -- Function: char * cfustring_get_buffer (cfustring_t * CFU_STR)

     Get the buffer used to hold the string.  Do not free() it, as it is used directly by cfustring and will be destroyed when cfustring_destroy() is called.

 -- Function: char * cfustring_get_buffer_copy (cfustring_t * CFU_STR)

     Same as cfustring_get_buffer(), except return a copy of the string. Caller is responsible for deallocating the buffer with free().

 -- Function: cfustring_t ** cfustring_split (cfustring_t * CFU_STR, size_t * NUM_STRINGS, size_t LIMIT, ...)

     Split cfu_str on one or more delimiting strings, e.g., cfustring_split(cfu_str, 2, 0, "\r\n", "\n").  Use a limit > 0 if you want to only get back a certain number of strings and ignore any extra delimiters.

 -- Function: char ** cfustring_split_to_c_str (cfustring_t * CFU_STR, size_t * NUM_STRINGS, size_t LIMIT, ...)

     Same as cfustring_split(), except return an array of C-strings. Caller is responsible for deallocating the buffers.

 -- Function: int cfustring_destroy (cfustring_t * CFU_STR)

     Free all resources allocated by cfu_str.

 -- Function: char * cfustring_dup_c_str (const char * STR)

     Duplicate the C string str.  Caller must free with free().

 -- Function: char * cfustring_dup_c_str_n (const char * STR, size_t N)

     Same as cfustring_dup_c_str(), but only copy at most n chars

 -- Function: size_t cfustring_sprintf (cfustring_t * CFU_STR, const char * FMT, ...);

     Like sprintf(), but writes to a self-extending string.

 -- Function: size_t cfustring_vsprintf (cfustring_t * CFU_STR, const char * FMT, va_list AP);
     Like vsprintf(), but writes to a self-extending string.

 -- Function: char * cfustring_sprintf_c_str (const char * FMT, ...)

     Similar to sprintf(), but allocates a C string of the appropriate size for you and returns it.

 -- Function: char ** cfustring_c_str_split (const char * C_STR, size_t * NUM_STRINGS, size_t LIMIT, ...)

     Like cfustring_split_to_c_str(), but split a char * instead of a cfustring_t *.

Conf
****

This needs to be better documented.

Apache-style conf files contain directives and containers. Directives are simple one line specifications with or without arguments, e.g.,

Doit Expires On LoadModule my_mod modules/my_mod.so

Containers have a type and a name associated with them and they in turn contain directives and/or containers, e.g.,

<MyContainer test1> Expires Off <DB devdb> DBHost db.example.com DBUser test_user </DB> </MyContainer>

Values may be quoted, e.g.

DBUser "test user"

But must be specified on a single line.  To escape quotes within a quoted string, use the '\' character.

 -- Function: int cfuconf_parse_file (char * FILE_PATH, cfuconf_t ** CONF, char ** ERROR)

     Parse the apache-like conf file specified by file_path, returning a pointer to a cfuconf_t structure in conf.  Returns zero on success, less than zero on error.  If an error occurs and error is not NULL, it will be set to an error message (which must be free()'d by the caller).

 -- Function: int cfuconf_parse_buffer (char * BUFFER, cfuconf_t ** CONF, char ** ERROR)

     Same as cfuconf_parse_file(), except assume the contents of the file are already in buffer.

 -- Function: void cfuconf_destroy (cfuconf_t * CONF)

     Free all resources used by the cfuconf_t structure

 -- Function: cfuhash_table_t * cfuconf_get_containers (cfuconf_t * CONF)

     Get a hash of containers at the top level of conf

 -- Function: cfuhash_table_t * cfuconf_get_directives (cfuconf_t * CONF)

     Get a hash of directives at the to level

 -- Function: int cfuconf_get_directive_one_arg (cfuconf_t * CONF, char * DIRECTIVE, char ** RVALUE)

     Get the value of the given directive, assuming there is only one argument

 -- Function: int cfuconf_get_directive_two_args (cfuconf_t * CONF, char * DIRECTIVE, char ** RVALUE, char ** RVALUE2)

     Get the value of the given directive, assuming there are two arguments

 -- Function: int cfuconf_get_directive_n_args (cfuconf_t * CONF, char * DIRECTIVE, size_t N, ...)

     Get the value of the given directives, with n arguments

Options
*******

Command-line arguments can be parsed with the following:

	cfuopt_t *opt = cfuopt_new();
	cfuopt_add_entry(opt, "verbose|v!", &verbose, "Verbosity", "");
	cfuopt_add_entry(opt, "file|f:s", &file, "File to load", "FILE");
	cfuopt_add_entry(opt, "count|c|n=i", &count, "Count to run", "COUNT");
	cfuopt_add_entry(opt, "scale|s:f", &scale, "Scaling factor", "SCALE");
	cfuopt_parse(opt, &argc, &argv, &error);
        /* do stuff here with the options */
       	cfuopt_destroy(opt);
        free(file);

 -- Function: cfuopt_t *cfuopt_new ()
     Returns a new options context.

 -- Function: void cfuopt_add_entry (cfuopt_t *CONTEXT, const char *OPT_STR, void *ARG_DATA, const char *DESCRIPTION, const char *ARG_DESCRIPTION)
     Adds to the list of known options.

 -- Function: void cfuopt_parse (cfuopt_t *CONTEXT, int *ARGC, char ***ARGV, char **ERROR)
     Parses the command line and modifies argc and argv to account for left over arguments.

 -- Function: char *cfuopt_get_help_str (cfuopt_t *CONTEXT)
     Returns a help string built from the entries added with cfuopt_add_entry().

 -- Function: void cfuopt_destroy (cfuopt_t *CONTEXT)
     Frees up resources used by the option parser.

Thread queue
************

cfuthread_queue provides a way to serialize requests for a resource where you want the resource to be accessed from a single thread only. For instance, for a database connection where making calls in separate threads does not work properly, you can use cfuthread_queue. cfuthread_queue_new() creates a new thread that waits for something to be added to the queue.  Once something is added, the thread will process the data by calling the function you pass as an argument to the cfuthread_queue_new() function.

 -- Function: cfuthread_queue_t * cfuthread_queue_new (cfuthread_queue_fn_t FN)

     Creates a new thread queue structure that will run the given function when a request is received.

 -- Function: cfuthread_queue_t * cfuthread_queue_new_with_cleanup (cfuthread_queue_fn_t FN, cfuthread_queue_init_t INIT_FN, void * INIT_ARG, cfuthread_queue_cleanup_t CLEANUP_FN, void * CLEANUP_ARG)

     Same as cfuthread_queue_new(), but with an initialization function that gets called with the argument init_arg when the thread is created, and a cleanup function that gets called with the argument cleanup_arg when the thread exits, e.g., when cfuthread_queue_destroy() is called.

 -- Function: void * cfuthread_queue_make_request (cfuthread_queue_t * TQ, void * DATA)

     Add a request to the queue.  data will get passed to the function fn given to cfuthread_queue_new when it reaches the front of the queue.

 -- Function: void cfuthread_queue_destroy (cfuthread_queue_t * TQ)

     Free up resources used by the queue, in addition to canceling the thread.

Timer
*****

 -- Function: cfutime_t *cfutime_new ();

     Return a new cfutime structure.

 -- Function: void cfutime_begin (cfutime_t *TIME)

     Start the timer.

 -- Function: void cfutime_end (cfutime_t * TIME)

     Stop the timer.

 -- Function: double cfutime_elapsed (cfutime_t * TIME)

     Return the number of seconds elapsed as a double.

 -- Function: void cfutime_free (cfutime_t * TIME)

     Deallocate resources allocated for time.

License
*******

Copyright © 2005 Don Owens All rights reserved.

This code is released under the BSD license:

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

* Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.