.\" t .fam H .\" Understrike macro .de us \\$1\l'|0\(ul' .. . . .\" Turn hyphenation off .nh .\" Load monospace fonts .if n \{\ . mso tty-char.tmac . ftr CR R . ftr CI I . ftr CB B .\} .if '\*[.T]'dvi' \ . ftr CB CW . . .\" Start the document .TH "SFI-Functions" "3" "25 May 2005" "BEAST-0.6.6-rc1" "BEAST-0.6.6-rc1" .SH NAME .PP SFI-Functions - SFI Function Reference .PP \fIDocument Revised:\fP Wed May 25 23:38:16 2005 .br .SH SYNOPSIS .PP .na \fB\f(CBg_file_test_all\fP\f1(\fI\f(CIfile\fP\f1, \fI\f(CItest\fP\f1); .br \fB\f(CBsfi_file_check\fP\f1(\fI\f(CIfile\fP\f1, \fI\f(CImode\fP\f1); .br \fB\f(CBsfi_file_crawler_add_search_path\fP\f1(\fI\f(CIself\fP\f1, \fI\f(CIpattern_paths\fP\f1, \fI\f(CIfile_pattern\fP\f1); .br \fB\f(CBsfi_file_crawler_add_tests\fP\f1(\fI\f(CIself\fP\f1, \fI\f(CItests\fP\f1); .br \fB\f(CBsfi_file_crawler_crawl\fP\f1(\fI\f(CIself\fP\f1); .br \fB\f(CBsfi_file_crawler_destroy\fP\f1(\fI\f(CIself\fP\f1); .br \fB\f(CBsfi_file_crawler_list_files\fP\f1(\fI\f(CIsearch_path\fP\f1, \fI\f(CIfile_pattern\fP\f1, \fI\f(CIfile_test\fP\f1); .br \fB\f(CBsfi_file_crawler_needs_crawl\fP\f1(\fI\f(CIself\fP\f1); .br \fB\f(CBsfi_file_crawler_new\fP\f1(); .br \fB\f(CBsfi_file_crawler_pop\fP\f1(\fI\f(CIself\fP\f1); .br \fB\f(CBsfi_file_crawler_set_cwd\fP\f1(\fI\f(CIself\fP\f1, \fI\f(CIcwd\fP\f1); .br \fB\f(CBsfi_guard_deregister\fP\f1(\fI\f(CIguard\fP\f1); .br \fB\f(CBsfi_guard_is_protected\fP\f1(\fI\f(CIvalue\fP\f1); .br \fB\f(CBsfi_guard_n_snap_values\fP\f1(); .br \fB\f(CBsfi_guard_protect\fP\f1(\fI\f(CIguard\fP\f1, \fI\f(CInth_hazard\fP\f1, \fI\f(CIvalue\fP\f1); .br \fB\f(CBsfi_guard_register\fP\f1(\fI\f(CIn_hazards\fP\f1); .br \fB\f(CBsfi_guard_snap_values\fP\f1(\fI\f(CIn_values\fP\f1, \fI\f(CIvalues\fP\f1); .br \fB\f(CBsfi_msg_default_handler\fP\f1(\fI\f(CImsg\fP\f1); .br \fB\f(CBsfi_msg_log_elist\fP\f1(\fI\f(CIlog_domain\fP\f1, \fI\f(CImtype\fP\f1, \fI\f(CIlbit1\fP\f1, \fI\f(CIlbit2\fP\f1, \fI\f(CI...\fP\f1); .br \fB\f(CBsfi_msg_log_printf\fP\f1(\fI\f(CIlog_domain\fP\f1, \fI\f(CIlevel\fP\f1, \fI\f(CIformat\fP\f1, \fI\f(CI...\fP\f1); .br \fB\f(CBsfi_msg_log_trampoline\fP\f1(\fI\f(CIlog_domain\fP\f1, \fI\f(CImtype\fP\f1, \fI\f(CIlbit1\fP\f1, \fI\f(CIlbit2\fP\f1, \fI\f(CIlbitargs\fP\f1, \fI\f(CIhandler\fP\f1, \fI\f(CIvbitlist\fP\f1); .br \fB\f(CBsfi_msg_set_thread_handler\fP\f1(\fI\f(CIhandler\fP\f1); .br \fB\f(CBsfi_msg_type_ident\fP\f1(\fI\f(CImtype\fP\f1); .br \fB\f(CBsfi_msg_type_label\fP\f1(\fI\f(CImtype\fP\f1); .br \fB\f(CBsfi_msg_type_lookup\fP\f1(\fI\f(CIident\fP\f1); .br \fB\f(CBsfi_msg_type_register\fP\f1(\fI\f(CIident\fP\f1, \fI\f(CIdefault_ouput\fP\f1, \fI\f(CIlabel\fP\f1, \fI\f(CIRETURN\fP\f1); .br \fB\f(CBsfi_path_get_filename\fP\f1(\fI\f(CIfilename\fP\f1, \fI\f(CIparentdir\fP\f1); .br \fB\f(CBsfi_ring_split\fP\f1(\fI\f(CIhead1\fP\f1, \fI\f(CIhead2\fP\f1); .br \fB\f(CBsfi_thread_abort\fP\f1(\fI\f(CIthread\fP\f1); .br \fB\f(CBsfi_thread_aborted\fP\f1(); .br \fB\f(CBsfi_thread_awake_after\fP\f1(\fI\f(CIstamp\fP\f1); .br \fB\f(CBsfi_thread_emit_wakeups\fP\f1(\fI\f(CIwakeup_stamp\fP\f1); .br \fB\f(CBsfi_thread_get_name\fP\f1(\fI\f(CIthread\fP\f1); .br \fB\f(CBsfi_thread_get_pid\fP\f1(\fI\f(CIthread\fP\f1); .br \fB\f(CBsfi_thread_queue_abort\fP\f1(\fI\f(CIthread\fP\f1); .br \fB\f(CBsfi_thread_run\fP\f1(\fI\f(CIname\fP\f1, \fI\f(CIfunc\fP\f1, \fI\f(CIuser_data\fP\f1); .br \fB\f(CBsfi_thread_self\fP\f1(); .br \fB\f(CBsfi_thread_self_pid\fP\f1(); .br \fB\f(CBsfi_thread_set_wakeup\fP\f1(\fI\f(CIwakeup_func\fP\f1, \fI\f(CIwakeup_data\fP\f1, \fI\f(CIdestroy\fP\f1); .br \fB\f(CBsfi_thread_sleep\fP\f1(\fI\f(CImax_useconds\fP\f1); .br \fB\f(CBsfi_thread_wakeup\fP\f1(\fI\f(CIthread\fP\f1); .br \fB\f(CBsfi_time_from_string\fP\f1(\fI\f(CItime_string\fP\f1); .br \fB\f(CBsfi_time_from_string_err\fP\f1(\fI\f(CItime_string\fP\f1, \fI\f(CIerror_p\fP\f1); .br \fB\f(CBsfi_time_from_utc\fP\f1(\fI\f(CIustime\fP\f1); .br \fB\f(CBsfi_time_system\fP\f1(); .br \fB\f(CBsfi_time_to_string\fP\f1(\fI\f(CIustime\fP\f1); .br \fB\f(CBsfi_time_to_utc\fP\f1(\fI\f(CIustime\fP\f1); .br .ad .SH DESCRIPTION .TP .PD 0 \fB\f(CBg_file_test_all\fP\f1(\fI\f(CIfile\fP\f1, \fI\f(CItest\fP\f1); .na .TS nokeep; l l l. \fI\f(CIconst gchar*\fP\f1 \fI\f(CIfile\fP\f1; T{ a file to test T} \fI\f(CIGFileTest \fP\f1 \fI\f(CItest\fP\f1; T{ bitfield of \fI\f(CIGFileTest\fP\f1 flags T} .TE .ad This is the AND version of \fB\f(CBg_file_test()\fP\f1. That is, all file tests specified in the \fI\f(CItest\fP\f1 bits have to succed for this function to return \fCTRUE\f1. This function is implemented via \fB\f(CBsfi_file_check()\fP\f1, which allowes for more detailed mode tests and is recommended over use of this function. Here is the list of possible \fI\f(CIGFileTest\fP\f1 flags: .br G_FILE_TEST_IS_REGULAR - test for a recular file .br G_FILE_TEST_IS_SYMLINK - test for a symlink .br G_FILE_TEST_IS_DIR - test for a directory .br G_FILE_TEST_IS_EXECUTABLE - test for an executable .br G_FILE_TEST_EXISTS - test whether the file exists .TP .PD 0 \fB\f(CBsfi_file_check\fP\f1(\fI\f(CIfile\fP\f1, \fI\f(CImode\fP\f1); .na .TS nokeep; l l l. \fI\f(CIconst gchar*\fP\f1 \fI\f(CIfile\fP\f1; T{ possibly relative filename T} \fI\f(CIconst gchar*\fP\f1 \fI\f(CImode\fP\f1; T{ feature string T} \h'-2m'\fI\f(CIRETURNS:\fP\f1 T{ \fCTRUE\f1 if \fI\f(CIfile\fP\f1 adhears to \fI\f(CImode\fP\f1 T} .TE .ad Perform various checks on \fI\f(CIfile\fP\f1 and return whether all checks passed. On failure, errno is set appropriately, and \fCFALSE\f1 is returned. Available features to be checked for are: .br e - \fI\f(CIfile\fP\f1 must exist .br r - \fI\f(CIfile\fP\f1 must be readable .br w - \fI\f(CIfile\fP\f1 must be writable .br x - \fI\f(CIfile\fP\f1 must be executable .br f - \fI\f(CIfile\fP\f1 must be a regular file .br d - \fI\f(CIfile\fP\f1 must be a directory .br l - \fI\f(CIfile\fP\f1 must be a symbolic link .br c - \fI\f(CIfile\fP\f1 must be a character device .br b - \fI\f(CIfile\fP\f1 must be a block device .br p - \fI\f(CIfile\fP\f1 must be a named pipe .br s - \fI\f(CIfile\fP\f1 must be a socket. .TP .PD 0 \fB\f(CBsfi_file_crawler_add_search_path\fP\f1(\fI\f(CIself\fP\f1, \fI\f(CIpattern_paths\fP\f1, \fI\f(CIfile_pattern\fP\f1); .na .TS nokeep; l l l. \fI\f(CISfiFileCrawler*\fP\f1 \fI\f(CIself\fP\f1; T{ valid \fI\f(CISfiFileCrawler\fP\f1 T} \fI\f(CIconst gchar*\fP\f1 \fI\f(CIpattern_paths\fP\f1; T{ colon (semicolon under win32) seperated search path T} \fI\f(CIconst gchar*\fP\f1 \fI\f(CIfile_pattern\fP\f1; T{ wildcard pattern for file names T} \h'-2m'\fI\f(CIRETURNS:\fP\f1 T{ a singly linked list with newly allocated strings T} .TE .ad This function takes a search path (possibly containing wildcards) and adds them to the file crawlers search list. If \fI\f(CIfile_pattern\fP\f1 is non \fCNULL\f1, it is appended to each directory element extracted from \fI\f(CIpattern_paths\fP\f1, before attempting file system searches. \fB\f(CBsfi_file_crawler_needs_crawl()\fP\f1 may return \fCTRUE\f1 after calling this function. .TP .PD 0 \fB\f(CBsfi_file_crawler_add_tests\fP\f1(\fI\f(CIself\fP\f1, \fI\f(CItests\fP\f1); .na .TS nokeep; l l l. \fI\f(CISfiFileCrawler*\fP\f1 \fI\f(CIself\fP\f1; T{ valid \fI\f(CISfiFileCrawler\fP\f1 T} \fI\f(CIGFileTest \fP\f1 \fI\f(CItests\fP\f1; T{ \fI\f(CIGFileTest\fP\f1 test flags T} .TE .ad By default, results returned by \fI\f(CIself\fP\f1 are only tested for existence. If additional file tests have to be met by the results, they can be set by this function. .TP .PD 0 \fB\f(CBsfi_file_crawler_crawl\fP\f1(\fI\f(CIself\fP\f1); .na .TS nokeep; l l l. \fI\f(CISfiFileCrawler*\fP\f1 \fI\f(CIself\fP\f1; T{ valid \fI\f(CISfiFileCrawler\fP\f1 T} .TE .ad Collect the next file or directory if possible, new results need not arrive after calling this function, and more than one may. This function does nothing if \fB\f(CBsfi_file_crawler_needs_crawl()\fP\f1 returns \fCFALSE\f1. .TP .PD 0 \fB\f(CBsfi_file_crawler_destroy\fP\f1(\fI\f(CIself\fP\f1); .na .TS nokeep; l l l. \fI\f(CISfiFileCrawler*\fP\f1 \fI\f(CIself\fP\f1; T{ valid \fI\f(CISfiFileCrawler\fP\f1 T} .TE .ad Destroy an existing file crawler and free any resources allocated by it. .TP .PD 0 \fB\f(CBsfi_file_crawler_list_files\fP\f1(\fI\f(CIsearch_path\fP\f1, \fI\f(CIfile_pattern\fP\f1, \fI\f(CIfile_test\fP\f1); .na .TS nokeep; l l l. \fI\f(CIconst gchar*\fP\f1 \fI\f(CIsearch_path\fP\f1; T{ colon (semicolon under win32) seperated search path with '?' and '*' wildcards T} \fI\f(CIconst gchar*\fP\f1 \fI\f(CIfile_pattern\fP\f1; T{ wildcard pattern for file names T} \fI\f(CIGFileTest \fP\f1 \fI\f(CIfile_test\fP\f1; T{ GFileTest file test condition (e.g. G_FILE_TEST_IS_REGULAR) or \fC0\f1 T} \h'-2m'\fI\f(CIRETURNS:\fP\f1 T{ an \fI\f(CISfiRing\fP\f1 with newly allocated strings T} .TE .ad Given a search path with wildcards, list all files matching \fI\f(CIfile_pattern\fP\f1, contained in the directories which the search path matches. Files that do not pass \fI\f(CIfile_test\fP\f1 are not listed. .TP .PD 0 \fB\f(CBsfi_file_crawler_needs_crawl\fP\f1(\fI\f(CIself\fP\f1); .na .TS nokeep; l l l. \fI\f(CISfiFileCrawler*\fP\f1 \fI\f(CIself\fP\f1; T{ valid \fI\f(CISfiFileCrawler\fP\f1 T} .TE .ad RETURNS: \fCTRUE\f1 if \fB\f(CBsfi_file_crawler_crawl()\fP\f1 should be called Figure whether collecting all matching files has finished now. If not, \fB\f(CBsfi_file_crawler_crawl()\fP\f1 needs to be called until this function returns \fCFALSE\f1. .TP .PD 0 \fB\f(CBsfi_file_crawler_new\fP\f1(); Create a new file crawler. A file crawler collects all files matching a given search path and file test. \fB\f(CBsfi_file_crawler_crawl()\fP\f1 needs to be called as long as \fB\f(CBsfi_file_crawler_needs_crawl()\fP\f1 returns \fCTRUE\f1 to collect all matching files. .TP .PD 0 \fB\f(CBsfi_file_crawler_pop\fP\f1(\fI\f(CIself\fP\f1); .na .TS nokeep; l l l. \fI\f(CISfiFileCrawler*\fP\f1 \fI\f(CIself\fP\f1; T{ valid \fI\f(CISfiFileCrawler\fP\f1 T} .TE .ad RETURNS: newly allocated string containig resulting filename Fetch next result if any or \fCNULL\f1. .TP .PD 0 \fB\f(CBsfi_file_crawler_set_cwd\fP\f1(\fI\f(CIself\fP\f1, \fI\f(CIcwd\fP\f1); .na .TS nokeep; l l l. \fI\f(CISfiFileCrawler*\fP\f1 \fI\f(CIself\fP\f1; T{ valid \fI\f(CISfiFileCrawler\fP\f1 T} \fI\f(CIconst gchar*\fP\f1 \fI\f(CIcwd\fP\f1; T{ absolute path T} .TE .ad Set the path to be assumed the current working directory. .TP .PD 0 \fB\f(CBsfi_guard_deregister\fP\f1(\fI\f(CIguard\fP\f1); .na .TS nokeep; l l l. \fI\f(CISfiGuard*\fP\f1 \fI\f(CIguard\fP\f1; T{ a valid \fI\f(CISfiGuard\fP\f1 as returned from \fB\f(CBsfi_guard_register()\fP\f1 T} .TE .ad Deregister a guard previously registered by a call to \fB\f(CBsfi_guard_register()\fP\f1. Deregistration is performed in constant time. .TP .PD 0 \fB\f(CBsfi_guard_is_protected\fP\f1(\fI\f(CIvalue\fP\f1); .na .TS nokeep; l l l. \fI\f(CIgpointer \fP\f1 \fI\f(CIvalue\fP\f1; T{ hazard pointer value T} \h'-2m'\fI\f(CIRETURNS:\fP\f1 T{ \fCTRUE\f1 if a hazard pointer protecting \fI\f(CIvalue\fP\f1 has been found T} .TE .ad Check whether \fI\f(CIvalue\fP\f1 is protected by a hazard pointer guard. If multiple pointer values are to be checked, use \fB\f(CBsfi_guard_snap_values()\fP\f1 instead, as this function has \fB\f(CBO(n_hazard_pointers)\fP\f1 time complexity. If only one pointer value needs to be looked up though, calling \fB\f(CBsfi_guard_is_protected()\fP\f1 will provide a result faster than calling \fB\f(CBsfi_guard_snap_values()\fP\f1 and looking up the pointer in the filled-in array. Lookup within hazard pointer arrays will always occour in ascending order to allow pointer migration as described in \fB\f(CBsfi_guard_snap_values()\fP\f1 and \fB\f(CBsfi_guard_register()\fP\f1. .TP .PD 0 \fB\f(CBsfi_guard_n_snap_values\fP\f1(); .na .TS nokeep; l l l. \h'-2m'\fI\f(CIRETURNS:\fP\f1 T{ an upper bound on the number of registered hazard pointers T} .TE .ad Retrieve an upper bound on the number of hazard pointer value slots currently required for a successfull call to \fB\f(CBsfi_guard_snap_values()\fP\f1. Note that a subsequent call to \fB\f(CBsfi_guard_snap_values()\fP\f1 may still fail due to addtional guards being registerted meanwhile. In such a case \fB\f(CBsfi_guard_n_snap_values()\fP\f1 and \fB\f(CBsfi_guard_snap_values()\fP\f1 can simply be called again. .TP .PD 0 \fB\f(CBsfi_guard_protect\fP\f1(\fI\f(CIguard\fP\f1, \fI\f(CInth_hazard\fP\f1, \fI\f(CIvalue\fP\f1); .na .TS nokeep; l l l. \fI\f(CISfiGuard*\fP\f1 \fI\f(CIguard\fP\f1; T{ a valid \fI\f(CISfiGuard\fP\f1 as returned from \fB\f(CBsfi_guard_register()\fP\f1 T} \fI\f(CIguint \fP\f1 \fI\f(CInth_hazard\fP\f1; T{ index of the hazard pointer to use for protection T} \fI\f(CIgpointer \fP\f1 \fI\f(CIvalue\fP\f1; T{ a hazardous pointer value or \fCNULL\f1 to reset protection T} .TE .ad Protect the node pointed to by \fI\f(CIvalue\fP\f1 from being destroyed by another thread and against the ABA problem caused by premature reuse. For this to work, threads destroying nodes of the type pointed to by \fI\f(CIvalue\fP\f1 need to suspend destruction as long as nodes are protected, which can by checked by calls to \fB\f(CBsfi_guard_is_protected()\fP\f1 or by searching the values returned from \fB\f(CBsfi_guard_snap_values()\fP\f1. Descriptions of safe memory reclamation and ABA problem detection via hazard pointers guards can be found in \fI\f(CIhttp://www.research.ibm.com/people/m/michael/podc-2002.pdf\fP , \fI\f(CIhttp://www.cs.brown.edu/people/mph/HerlihyLM02/smli_tr-2002-112.pdf\fP , \fI\f(CIhttp://research.sun.com/scalable/Papers/CATS2003.pdf\fP and \fI\f(CIhttp://www.research.ibm.com/people/m/michael/ieeetpds-2004.pdf\fP . The exact sequence of steps to protect and access a node is as follows: .br \fC1\f1) Store the adress of a node to be protected in a hazard pointer .br \fC2\f1) Verify that the hazard pointer points to a valid node .br \fC3\f1) Dereference the node only as long as it's protected by the hazard pointer. .br For example: .br \fC0\f1: SfiGuard *guard = sfi_guard_register (\fC1\f1); .br \fC1\f1: peek_head_label: .br \fC2\f1: auto GSList *node = shared_list_head; .br \fC3\f1: sfi_guard_protect (guard, \fC0\f1, node); .br \fC4\f1: if (node != shared_list_head) goto peek_head_label; .br \fC5\f1: operate_on_protected_node (node); .br \fC6\f1: sfi_guard_deregister (guard); .TP .PD 0 \fB\f(CBsfi_guard_register\fP\f1(\fI\f(CIn_hazards\fP\f1); .na .TS nokeep; l l l. \fI\f(CIguint \fP\f1 \fI\f(CIn_hazards\fP\f1; T{ number of required hazard pointers T} \h'-2m'\fI\f(CIRETURNS:\fP\f1 T{ a valid \fI\f(CISfiGuard\fP\f1 T} .TE .ad Retrieve a new guard for node protection of the current thread. The exact mechanism of protection is described in \fB\f(CBsfi_guard_protect()\fP\f1. Note that \fB\f(CBsfi_guard_snap_values()\fP\f1 will walk the hazard pointer array in ascending order, so that pointers may migrate from array positions with a lower index to positions with a higher index while retaining protection, according to condition C2 as described in \fI\f(CIhttp://www.research.ibm.com/people/m/michael/podc-2002.pdf\fP . If an equally or bigger sized hazard pointer array was previously deregistered by this thread, registration takes constant time. .TP .PD 0 \fB\f(CBsfi_guard_snap_values\fP\f1(\fI\f(CIn_values\fP\f1, \fI\f(CIvalues\fP\f1); .na .TS nokeep; l l l. \fI\f(CIguint*\fP\f1 \fI\f(CIn_values\fP\f1; T{ location of n_values variable T} \fI\f(CIgpointer*\fP\f1 \fI\f(CIvalues\fP\f1; T{ value array to fill in T} \h'-2m'\fI\f(CIRETURNS:\fP\f1 T{ \fCTRUE\f1 if \fI\f(CIvalues\fP\f1 provided enough space and is filled T} .TE .ad Make a snapshot of all non-NULL hazard pointer values. \fCTRUE\f1 is returned if the number of non-NULL hazard pointer values didn't exceed the size of the input value array provided by \fI\f(CIn_values\fP\f1, and all values are returned in the array pointed to by \fI\f(CIvalues\fP\f1. The number of values filled in is returned in \fI\f(CIn_values\fP\f1. \fCFALSE\f1 is returned if not enough space was available to return all non-NULL values. \fB\f(CBsfi_guard_n_snap_values()\fP\f1 may be used to retrieve the current upper bound on the number of registered guards. Note that a successive call to \fB\f(CBsfi_guard_snap_values()\fP\f1 with the requested number of value slots supplied may still fail, because additional guards may have been registered meanwhile. In such a case \fB\f(CBsfi_guard_n_snap_values()\fP\f1 and \fB\f(CBsfi_guard_snap_values()\fP\f1 can simply be called again. This funciton will always walk the hazard pointer arrays supplied by \fB\f(CBsfi_guard_register()\fP\f1 in ascending order, to allow pointer migration from lower to higher array indieces while retaining protection. The returned pointer values are unordered, so in order to perform multiple pointer lookups, we recommend sorting the returned array and then doing binary lookups. However if only a single pointer is to be looked up, calling \fB\f(CBsfi_guard_is_protected()\fP\f1 should be considered. .TP .PD 0 \fB\f(CBsfi_msg_default_handler\fP\f1(\fI\f(CImsg\fP\f1); .na .TS nokeep; l l l. \fI\f(CIconst SfiMessage*\fP\f1 \fI\f(CImsg\fP\f1; T{ T} .TE .ad This is the standard message handler, it produces \fI\f(CImessage\fP\f1 in a prominent way on stderr. This function is MT-safe and may be called from any thread. .TP .PD 0 \fB\f(CBsfi_msg_log_elist\fP\f1(\fI\f(CIlog_domain\fP\f1, \fI\f(CImtype\fP\f1, \fI\f(CIlbit1\fP\f1, \fI\f(CIlbit2\fP\f1, \fI\f(CI...\fP\f1); .na .TS nokeep; l l l. \fI\f(CIlog_domain\fP\f1; T{ log domain T} \fI\f(CImtype\fP\f1; T{ one of \fCSFI_MSG_ERROR\f1, \fCSFI_MSG_WARNING\f1, \fCSFI_MSG_INFO\f1, \fCSFI_MSG_DIAG\f1 T} \fI\f(CIlbit1\fP\f1; T{ msg bit T} \fI\f(CIlbit2\fP\f1; T{ msg bit T} \fI\f(CI...\fP\f1; T{ list of more msg bits, NULL terminated T} .TE .ad Log a message through SFIs logging mechanism. The current value of errno is preserved around calls to this function. Usually this function isn't used directly, but \fB\f(CBsfi_log_msg()\fP\f1 is called instead which does not require \fCNULL\f1 termination of its argument list and automates the \fI\f(CIlog_domain\fP\f1 argument. The \fI\f(CIlog_domain\fP\f1 indicates the calling module and relates to \fCG_LOG_DOMAIN\f1 as used by \fB\f(CBg_log()\fP\f1. The msg bit arguments passed in form various parts of the log message, the following macro set is provided to construct the parts from printf-style argument lists: - \fB\f(CBSFI_MSG_TITLE()\fP\f1: format message title - \fB\f(CBSFI_MSG_TEXT1()\fP\f1: format primary message (also \fB\f(CBSFI_MSG_PRIMARY()\fP\f1) - \fB\f(CBSFI_MSG_TEXT2()\fP\f1: format secondary message, optional (also \fB\f(CBSFI_MSG_SECONDARY()\fP\f1) - \fB\f(CBSFI_MSG_TEXT3()\fP\f1: format details of the message, optional (also \fB\f(CBSFI_MSG_DETAIL()\fP\f1) - \fB\f(CBSFI_MSG_CHECK()\fP\f1: format configuration check statement to enable/disable log messages of this type. This function is MT-safe and may be called from any thread. .TP .PD 0 \fB\f(CBsfi_msg_log_printf\fP\f1(\fI\f(CIlog_domain\fP\f1, \fI\f(CIlevel\fP\f1, \fI\f(CIformat\fP\f1, \fI\f(CI...\fP\f1); .na .TS nokeep; l l l. \fI\f(CIlog_domain\fP\f1; T{ log domain T} \fI\f(CIlevel\fP\f1; T{ one of \fCSFI_MSG_ERROR\f1, \fCSFI_MSG_WARNING\f1, \fCSFI_MSG_INFO\f1, \fCSFI_MSG_DIAG\f1 or \fCSFI_MSG_DEBUG\f1 T} \fI\f(CIformat\fP\f1; T{ printf-like format T} \fI\f(CI...\fP\f1; T{ printf-like arguments T} .TE .ad Log a message through SFIs logging mechanism. The current value of errno is preserved around calls to this function. Usually this function isn't used directly, but through one of \fB\f(CBsfi_debug()\fP\f1, \fB\f(CBsfi_diag()\fP\f1, \fB\f(CBsfi_info()\fP\f1, \fB\f(CBsfi_warn()\fP\f1 or \fB\f(CBsfi_error()\fP\f1. The \fI\f(CIlog_domain\fP\f1 indicates the calling module and relates to \fCG_LOG_DOMAIN\f1 as used by \fB\f(CBg_log()\fP\f1. This function is MT-safe and may be called from any thread. .TP .PD 0 \fB\f(CBsfi_msg_log_trampoline\fP\f1(\fI\f(CIlog_domain\fP\f1, \fI\f(CImtype\fP\f1, \fI\f(CIlbit1\fP\f1, \fI\f(CIlbit2\fP\f1, \fI\f(CIlbitargs\fP\f1, \fI\f(CIhandler\fP\f1, \fI\f(CIvbitlist\fP\f1); .na .TS nokeep; l l l. \fI\f(CIlog_domain\fP\f1; T{ log domain T} \fI\f(CImtype\fP\f1; T{ one of \fCSFI_MSG_ERROR\f1, \fCSFI_MSG_WARNING\f1, \fCSFI_MSG_INFO\f1, \fCSFI_MSG_DIAG\f1 T} \fI\f(CIlbit1\fP\f1; T{ msg bit T} \fI\f(CIlbit2\fP\f1; T{ msg bit T} \fI\f(CIlbitargs\fP\f1; T{ va_list list of more msg bits, NULL terminated T} \fI\f(CIhandler\fP\f1; T{ message handler T} \fI\f(CIvbitlist\fP\f1; T{ NULL terminated array of msg bits T} .TE .ad Construct a log message from the arguments given and let \fI\f(CIhandler\fP\f1 process it. This function performs no logging on its own, it is used internally by \fB\f(CBsfi_log_msg_elist()\fP\f1 to collect arguments and construct a message. All logging functionality has to be implemented by \fI\f(CIhandler\fP\f1. Note that all thread-local msg bits are deleted after invokation of this funtcion, so all msg bits created in the current thread are invalid after calling this function. Direct use of this function is not recommended except for implementations of logging mechanisms. This function is MT-safe and may be called from any thread. .TP .PD 0 \fB\f(CBsfi_msg_set_thread_handler\fP\f1(\fI\f(CIhandler\fP\f1); .na .TS nokeep; l l l. \fI\f(CISfiMsgHandler \fP\f1 \fI\f(CIhandler\fP\f1; T{ a valid \fI\f(CISfiMsgHandler\fP\f1 or \fCNULL\f1 T} .TE .ad Set the handler function for messages logged in the current thread. If \fCNULL\f1 is specified as handler, the standard handler will be used. For handler implementations that require an extra data argument, see \fB\f(CBsfi_thread_set_qdata()\fP\f1. This function is MT-safe and may be called from any thread. .TP .PD 0 \fB\f(CBsfi_msg_type_ident\fP\f1(\fI\f(CImtype\fP\f1); .na .TS nokeep; l l l. \fI\f(CISfiMsgType \fP\f1 \fI\f(CImtype\fP\f1; T{ T} .TE .ad Retrive the string identifying the message type \fI\f(CItype\fP\f1. For invalid (non registered) message types, \fCNULL\f1 is returned. This function is MT-safe and may be called from any thread. .TP .PD 0 \fB\f(CBsfi_msg_type_label\fP\f1(\fI\f(CImtype\fP\f1); .na .TS nokeep; l l l. \fI\f(CISfiMsgType \fP\f1 \fI\f(CImtype\fP\f1; T{ T} .TE .ad Retrive the label identifying the message type \fI\f(CItype\fP\f1. Usually, this is a translated version of \fB\f(CBsfi_msg_type_ident()\fP\f1 or \fCNULL\f1 if non was registered with the message type. This function is MT-safe and may be called from any thread. .TP .PD 0 \fB\f(CBsfi_msg_type_lookup\fP\f1(\fI\f(CIident\fP\f1); .na .TS nokeep; l l l. \fI\f(CIconst gchar*\fP\f1 \fI\f(CIident\fP\f1; T{ message identifier, e.g. "error", "warning", "info", etc... T} .TE .ad Find the message type correspondign to \fI\f(CIident\fP\f1. If no message type was found \fC0\f1 is returned (note that \fC0\f1 is also the value of \fCSFI_MSG_NONE\f1). This function is MT-safe and may be called from any thread. .TP .PD 0 \fB\f(CBsfi_msg_type_register\fP\f1(\fI\f(CIident\fP\f1, \fI\f(CIdefault_ouput\fP\f1, \fI\f(CIlabel\fP\f1, \fI\f(CIRETURN\fP\f1); .na .TS nokeep; l l l. \fI\f(CIident\fP\f1; T{ message identifier T} \fI\f(CIdefault_ouput\fP\f1; T{ an existing \fI\f(CISfiMsgType\fP\f1 or \fCFALSE\f1 or \fCTRUE\f1 T} \fI\f(CIlabel\fP\f1; T{ a translated version of \fI\f(CIident\fP\f1 T} \fI\f(CIRETURN\fP\f1; T{ message type id T} .TE .ad Register a new message type with identifier \fI\f(CIident\fP\f1 and user digestible name \fI\f(CIlabel\fP\f1. If this function is called multiple times with the same identifier, the type id acquired by the first call will be returned and the other arguments are ignored. As long as the new message type isn't configured individually via \fB\f(CBsfi_msg_enable()\fP\f1, \fB\f(CBsfi_msg_allow()\fP\f1 or their complements, it shares the configuration of \fI\f(CIdefault_ouput\fP\f1. If \fCFALSE\f1 or \fCTRUE\f1 is passed as \fI\f(CIdefault_ouput\fP\f1, this corresponds to \fCSFI_MSG_NONE\f1 or \fCSFI_MSG_FATAL\f1 respectively which are unconfigrable and always have their output disabled or enabled respectively. As an exception to the rest of the message API, this function may be called before \fB\f(CBsfi_init()\fP\f1. However note, that MT-safety is only ensured for calls occouring after \fB\f(CBsfi_init()\fP\f1. This function is MT-safe and may be called from any thread. .TP .PD 0 \fB\f(CBsfi_path_get_filename\fP\f1(\fI\f(CIfilename\fP\f1, \fI\f(CIparentdir\fP\f1); .na .TS nokeep; l l l. \fI\f(CIconst gchar*\fP\f1 \fI\f(CIfilename\fP\f1; T{ possibly relative filename T} \fI\f(CIconst gchar*\fP\f1 \fI\f(CIparentdir\fP\f1; T{ possibly relative parent directory path T} \h'-2m'\fI\f(CIRETURNS:\fP\f1 T{ a newly allocated absolute pathname T} .TE .ad Construct an absolute filename from \fI\f(CIfilename\fP\f1, using \fI\f(CIparentdir\fP\f1 as parent directory if \fI\f(CIfilename\fP\f1 is not absolute. If \fI\f(CIparentdir\fP\f1 is not absolute, it is assumed to be current directory relative. An exception are filenames starting out with '~' and '~USER', these are interpreted to refer to '/home' or '/home/USER' respectively. .TP .PD 0 \fB\f(CBsfi_ring_split\fP\f1(\fI\f(CIhead1\fP\f1, \fI\f(CIhead2\fP\f1); .na .TS nokeep; l l l. \fI\f(CISfiRing*\fP\f1 \fI\f(CIhead1\fP\f1; T{ a non-empty ring T} \fI\f(CISfiRing*\fP\f1 \fI\f(CIhead2\fP\f1; T{ a ring node different from \fI\f(CIhead1\fP\f1 contained in \fI\f(CIhead1\fP\f1 T} \h'-2m'\fI\f(CIRETURNS:\fP\f1 T{ \fI\f(CIhead2\fP\f1 for convenience T} .TE .ad Split a ring into two parts, starting the second ring with \fI\f(CIhead2\fP\f1. \fI\f(CIhead2\fP\f1 must therefore be non-NULL and must be contained in the ring formed by \fI\f(CIhead1\fP\f1. .TP .PD 0 \fB\f(CBsfi_thread_abort\fP\f1(\fI\f(CIthread\fP\f1); .na .TS nokeep; l l l. \fI\f(CISfiThread*\fP\f1 \fI\f(CIthread\fP\f1; T{ thread to abort T} .TE .ad Abort a currently running thread. This function does not return until the thread in question terminated execution. Note that the thread handle gets invalidated with invocation of \fB\f(CBsfi_thread_abort()\fP\f1 or \fB\f(CBsfi_thread_queue_abort()\fP\f1. .TP .PD 0 \fB\f(CBsfi_thread_aborted\fP\f1(); .na .TS nokeep; l l l. \h'-2m'\fI\f(CIRETURNS:\fP\f1 T{ \fCTRUE\f1 if the thread should abort execution T} .TE .ad Find out if the currently running thread should be aborted (the thread is supposed to return from its main thread function). This function or alternatively \fB\f(CBsfi_thread_sleep()\fP\f1 should be called periodically, to react to thread abortion requests and to update internal accounting information. .TP .PD 0 \fB\f(CBsfi_thread_awake_after\fP\f1(\fI\f(CIstamp\fP\f1); .na .TS nokeep; l l l. \fI\f(CIguint64 \fP\f1 \fI\f(CIstamp\fP\f1; T{ stamp to trigger wakeup T} .TE .ad Wake the current thread up at the next invocation of \fB\f(CBsfi_thread_emit_wakeups()\fP\f1 with a wakup_stamp greater than \fI\f(CIstamp\fP\f1. .TP .PD 0 \fB\f(CBsfi_thread_emit_wakeups\fP\f1(\fI\f(CIwakeup_stamp\fP\f1); .na .TS nokeep; l l l. \fI\f(CIguint64 \fP\f1 \fI\f(CIwakeup_stamp\fP\f1; T{ wakeup stamp to trigger wakeups T} .TE .ad Wake all currently sleeping threads up which queued a wakeup through \fB\f(CBsfi_thread_awake_after()\fP\f1 with a stamp smaller than \fI\f(CIwakeup_stamp\fP\f1. .TP .PD 0 \fB\f(CBsfi_thread_get_name\fP\f1(\fI\f(CIthread\fP\f1); .na .TS nokeep; l l l. \fI\f(CISfiThread*\fP\f1 \fI\f(CIthread\fP\f1; T{ a valid \fCSfiThread\f1 handle T} \h'-2m'\fI\f(CIRETURNS:\fP\f1 T{ thread name T} .TE .ad Return the name of \fI\f(CIthread\fP\f1 as specified upon invokation of \fB\f(CBsfi_thread_run()\fP\f1 or assigned by \fB\f(CBsfi_thread_set_name()\fP\f1. .TP .PD 0 \fB\f(CBsfi_thread_get_pid\fP\f1(\fI\f(CIthread\fP\f1); .na .TS nokeep; l l l. \fI\f(CISfiThread*\fP\f1 \fI\f(CIthread\fP\f1; T{ a valid \fCSfiThread\f1 handle T} \h'-2m'\fI\f(CIRETURNS:\fP\f1 T{ thread id T} .TE .ad Return the specific id for \fI\f(CIthread\fP\f1. This function is highly system dependant. The thread id may deviate from the overall process id or not. On linux, threads have their own id, allthough since kernel \fC2.6\f1, they share the same process id. .TP .PD 0 \fB\f(CBsfi_thread_queue_abort\fP\f1(\fI\f(CIthread\fP\f1); .na .TS nokeep; l l l. \fI\f(CISfiThread*\fP\f1 \fI\f(CIthread\fP\f1; T{ thread to abort T} .TE .ad Same as \fB\f(CBsfi_thread_abort()\fP\f1, but returns as soon as possible, even if thread hasn't stopped execution yet. Note that the thread handle gets invalidated with invocation of \fB\f(CBsfi_thread_abort()\fP\f1 or \fB\f(CBsfi_thread_queue_abort()\fP\f1. .TP .PD 0 \fB\f(CBsfi_thread_run\fP\f1(\fI\f(CIname\fP\f1, \fI\f(CIfunc\fP\f1, \fI\f(CIuser_data\fP\f1); .na .TS nokeep; l l l. \fI\f(CIconst gchar*\fP\f1 \fI\f(CIname\fP\f1; T{ thread name T} \fI\f(CISfiThreadFunc \fP\f1 \fI\f(CIfunc\fP\f1; T{ function to execute in new thread T} \fI\f(CIgpointer \fP\f1 \fI\f(CIuser_data\fP\f1; T{ user data to pass into \fI\f(CIfunc\fP\f1 T} \h'-2m'\fI\f(CIRETURNS:\fP\f1 T{ new thread handle or \fCNULL\f1 in case of error T} .TE .ad Create a new thread running \fI\f(CIfunc\fP\f1. .TP .PD 0 \fB\f(CBsfi_thread_self\fP\f1(); .na .TS nokeep; l l l. \h'-2m'\fI\f(CIRETURNS:\fP\f1 T{ thread handle T} .TE .ad Return the thread handle of the currently running thread. .TP .PD 0 \fB\f(CBsfi_thread_self_pid\fP\f1(); .na .TS nokeep; l l l. \h'-2m'\fI\f(CIRETURNS:\fP\f1 T{ thread id T} .TE .ad Return the thread specific id. This function is highly system dependant. The thread id may deviate from the overall process id or not. On linux, threads have their own id, allthough since kernel \fC2.6\f1, they share the same process id. .TP .PD 0 \fB\f(CBsfi_thread_set_wakeup\fP\f1(\fI\f(CIwakeup_func\fP\f1, \fI\f(CIwakeup_data\fP\f1, \fI\f(CIdestroy\fP\f1); .na .TS nokeep; l l l. \fI\f(CISfiThreadWakeup \fP\f1 \fI\f(CIwakeup_func\fP\f1; T{ wakeup function to be called by \fB\f(CBsfi_thread_wakeup()\fP\f1 T} \fI\f(CIgpointer \fP\f1 \fI\f(CIwakeup_data\fP\f1; T{ data passed into \fB\f(CBwakeup_func()\fP\f1 T} \fI\f(CIGDestroyNotify \fP\f1 \fI\f(CIdestroy\fP\f1; T{ destroy handler for \fI\f(CIwakeup_data\fP\f1 T} .TE .ad Set the wakeup function for the current thread. This enables the thread to be woken up through \fB\f(CBsfi_thread_wakeup()\fP\f1 even if not sleeping in \fB\f(CBsfi_thread_sleep()\fP\f1. The wakeup function must be thread-safe, so it may be called from any thread, and it should be fast, because the global thread system lock is held during its invokation. Per thread, the wakeup function may be set only once. .TP .PD 0 \fB\f(CBsfi_thread_sleep\fP\f1(\fI\f(CImax_useconds\fP\f1); .na .TS nokeep; l l l. \fI\f(CIglong \fP\f1 \fI\f(CImax_useconds\fP\f1; T{ maximum amount of micro seconds to sleep (-\fC1\f1 for infinite time) T} \h'-2m'\fI\f(CIRETURNS:\fP\f1 T{ \fCTRUE\f1 while the thread should continue execution T} .TE .ad Sleep for the amount of time given. This function may get interrupted by wakeup requests from \fB\f(CBsfi_thread_wakeup()\fP\f1, abort requests from \fB\f(CBsfi_thread_queue_abort()\fP\f1 or other means. It returns whether the thread is supposed to continue execution after waking up. This function or alternatively \fB\f(CBsfi_thread_aborted()\fP\f1 should be called periodically, to react to thread abortion requests and to update internal accounting information. .TP .PD 0 \fB\f(CBsfi_thread_wakeup\fP\f1(\fI\f(CIthread\fP\f1); .na .TS nokeep; l l l. \fI\f(CISfiThread*\fP\f1 \fI\f(CIthread\fP\f1; T{ thread to wake up T} .TE .ad Wake up a currently sleeping thread. In practice, this function simply causes the next call to \fB\f(CBsfi_thread_sleep()\fP\f1 within \fI\f(CIthread\fP\f1 to last for \fC0\f1 seconds. .TP .PD 0 \fB\f(CBsfi_time_from_string\fP\f1(\fI\f(CItime_string\fP\f1); .na .TS nokeep; l l l. \fI\f(CIconst gchar*\fP\f1 \fI\f(CItime_string\fP\f1; T{ string containing human readable date and time T} \h'-2m'\fI\f(CIRETURNS:\fP\f1 T{ parsed time in micro seconds or \fC0\f1 on error T} .TE .ad Simple variant of \fB\f(CBsfi_time_from_string_err()\fP\f1. .TP .PD 0 \fB\f(CBsfi_time_from_string_err\fP\f1(\fI\f(CItime_string\fP\f1, \fI\f(CIerror_p\fP\f1); .na .TS nokeep; l l l. \fI\f(CIconst gchar*\fP\f1 \fI\f(CItime_string\fP\f1; T{ string containing human readable date and time T} \fI\f(CIgchar**\fP\f1 \fI\f(CIerror_p\fP\f1; T{ location for newly allocated string containing conversion errors T} \h'-2m'\fI\f(CIRETURNS:\fP\f1 T{ parsed time in micro seconds, may be \fC0\f1 on error T} .TE .ad Parse date and time from a string of characters and indicate possible errors. Several attempts are made to reconstruct a valid date and time despite possible errors. However, if all attempts fail, the returned time is \fC0.\f1 The time returned is UTC, refer to \fB\f(CBsfi_time_from_utc()\fP\f1 in order to retrieve the local standard time. .TP .PD 0 \fB\f(CBsfi_time_from_utc\fP\f1(\fI\f(CIustime\fP\f1); .na .TS nokeep; l l l. \fI\f(CISfiTime \fP\f1 \fI\f(CIustime\fP\f1; T{ UTC relative time in micro seconds T} \h'-2m'\fI\f(CIRETURNS:\fP\f1 T{ local standard time in micro seconds T} .TE .ad Convert the Coordinated Universal Time (UTC) \fI\f(CIustime\fP\f1 into local standard time. This function is MT-safe and may be called from any thread. .TP .PD 0 \fB\f(CBsfi_time_system\fP\f1(); .na .TS nokeep; l l l. \h'-2m'\fI\f(CIRETURNS:\fP\f1 T{ Current system time in micro seconds T} .TE .ad Get the current system time in micro seconds. Subsequent calls to this function do not necessarily return greater values. In fact, a second call may return a value smaller than the first call under certain system conditions. The time returned is UTC, refer to \fB\f(CBsfi_time_from_utc()\fP\f1 in order to retrieve the local standard time. This function is MT-safe and may be called from any thread. .TP .PD 0 \fB\f(CBsfi_time_to_string\fP\f1(\fI\f(CIustime\fP\f1); .na .TS nokeep; l l l. \fI\f(CISfiTime \fP\f1 \fI\f(CIustime\fP\f1; T{ time in micro seconds T} \h'-2m'\fI\f(CIRETURNS:\fP\f1 T{ newly allocated string T} .TE .ad Retrieve the time \fI\f(CIustime\fP\f1 in human readable form. The returned time string describes UTC time and thus contains no time zone or UTC offset information. .TP .PD 0 \fB\f(CBsfi_time_to_utc\fP\f1(\fI\f(CIustime\fP\f1); .na .TS nokeep; l l l. \fI\f(CISfiTime \fP\f1 \fI\f(CIustime\fP\f1; T{ local standard time in micro seconds T} \h'-2m'\fI\f(CIRETURNS:\fP\f1 T{ UTC relative time in micro seconds T} .TE .ad Convert the local standard time \fI\f(CIustime\fP\f1 into Coordinated Universal Time (UTC). This function is MT-safe and may be called from any thread. .PP .br .PP \fIDocument Revised:\fP Wed May 25 23:38:16 2005 .br