You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							486 lines
						
					
					
						
							13 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							486 lines
						
					
					
						
							13 KiB
						
					
					
				
								/* /////////////////////////////////////////////////////////////////////////
							 | 
						|
								 * File:        test/component/test.component.be.file.threading/test.component.be.file.threading.cpp
							 | 
						|
								 *
							 | 
						|
								 * Purpose:     Implementation file for the test.component.be.file.threading project.
							 | 
						|
								 *
							 | 
						|
								 * Created:     3rd July 2009
							 | 
						|
								 * Updated:     10th January 2011
							 | 
						|
								 *
							 | 
						|
								 * Status:      Wizard-generated
							 | 
						|
								 *
							 | 
						|
								 * License:     (Licensed under the Synesis Software Open License)
							 | 
						|
								 *
							 | 
						|
								 *              Copyright (c) 2009-2011, Synesis Software Pty Ltd.
							 | 
						|
								 *              All rights reserved.
							 | 
						|
								 *
							 | 
						|
								 *              www:        http://www.synesis.com.au/software
							 | 
						|
								 *
							 | 
						|
								 * ////////////////////////////////////////////////////////////////////// */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								#include <pantheios/util/test/compiler_warnings_suppression.first_include.h>
							 | 
						|
								
							 | 
						|
								/* Pantheios Header Files */
							 | 
						|
								#include <pantheios/pan.hpp>
							 | 
						|
								#include <pantheios/backends/be.N.h>
							 | 
						|
								#include <pantheios/backends/bec.console.h>
							 | 
						|
								#include <pantheios/backends/bec.file.h>
							 | 
						|
								#include <pantheios/frontends/fe.N.h>
							 | 
						|
								#include <pantheios/inserters/args.hpp>
							 | 
						|
								#include <pantheios/inserters/blob.hpp>
							 | 
						|
								#include <pantheios/inserters/exception.hpp>
							 | 
						|
								#include <pantheios/inserters/integer.hpp>
							 | 
						|
								
							 | 
						|
								/* STLSoft Header Files */
							 | 
						|
								#include <stlsoft/string/split_functions.hpp>
							 | 
						|
								#include <stlsoft/string/string_view.hpp>
							 | 
						|
								#include <platformstl/filesystem/file_lines.hpp>
							 | 
						|
								#include <platformstl/filesystem/filesystem_traits.hpp>
							 | 
						|
								#include <platformstl/synch/sleep_functions.h>
							 | 
						|
								
							 | 
						|
								/* Standard C++ Header Files */
							 | 
						|
								#include <exception>
							 | 
						|
								
							 | 
						|
								#if defined(PLATFORMSTL_OS_IS_UNIX)
							 | 
						|
								
							 | 
						|
								 /* PThreads Header Files */
							 | 
						|
								# include <pthread.h>
							 | 
						|
								# include <sched.h>
							 | 
						|
								
							 | 
						|
								 /* UNIXEm Header Files */
							 | 
						|
								# if defined(_WIN32) || \
							 | 
						|
								     defined(_WIN64)
							 | 
						|
								#  include <unixem/unixem.h>
							 | 
						|
								# endif /* Win32 || Win64 */
							 | 
						|
								
							 | 
						|
								#elif defined(PLATFORMSTL_OS_IS_WINDOWS)
							 | 
						|
								
							 | 
						|
								# define WINSTL_ERROR_DESC_NO_IMPLICIT_CONVERSION
							 | 
						|
								# include <winstl/error/error_desc.hpp>
							 | 
						|
								
							 | 
						|
								# include <windows.h>
							 | 
						|
								
							 | 
						|
								#else /* ? OS */
							 | 
						|
								# error Operating system not discriminated
							 | 
						|
								#endif /* OS */
							 | 
						|
								
							 | 
						|
								/* Standard C Header Files */
							 | 
						|
								#include <stdio.h>
							 | 
						|
								#include <stdlib.h>
							 | 
						|
								
							 | 
						|
								#if defined(_MSC_VER) && \
							 | 
						|
								    defined(_DEBUG)
							 | 
						|
								# define USE_MSC_VER_CRT_MEM_CHECKS
							 | 
						|
								# include <crtdbg.h>
							 | 
						|
								#endif /* _MSC_VER) && _DEBUG */
							 | 
						|
								
							 | 
						|
								#include <pantheios/util/test/compiler_warnings_suppression.last_include.h>
							 | 
						|
								
							 | 
						|
								/* ////////////////////////////////////////////////////////////////////// */
							 | 
						|
								
							 | 
						|
								#define PSTR(x)         PANTHEIOS_LITERAL_STRING(x)
							 | 
						|
								
							 | 
						|
								/* /////////////////////////////////////////////////////////////////////////
							 | 
						|
								 * Character encoding
							 | 
						|
								 */
							 | 
						|
								
							 | 
						|
								#ifdef PANTHEIOS_USE_WIDE_STRINGS
							 | 
						|
								
							 | 
						|
								# define XTESTS_TEST_STRING_EQUAL       XTESTS_TEST_WIDE_STRING_EQUAL
							 | 
						|
								
							 | 
						|
								#else /* ? PANTHEIOS_USE_WIDE_STRINGS */
							 | 
						|
								
							 | 
						|
								# define XTESTS_TEST_STRING_EQUAL       XTESTS_TEST_MULTIBYTE_STRING_EQUAL
							 | 
						|
								
							 | 
						|
								#endif /* PANTHEIOS_USE_WIDE_STRINGS */
							 | 
						|
								
							 | 
						|
								/* /////////////////////////////////////////////////////////////////////////
							 | 
						|
								 * Constants and definitions
							 | 
						|
								 */
							 | 
						|
								
							 | 
						|
								#ifdef _DEBUG
							 | 
						|
								const size_t    LOG_ITERATIONS      =   10;
							 | 
						|
								const size_t    SET_PATH_DELAY      =   1000 * 100;
							 | 
						|
								#else /* ? _DEBUG */
							 | 
						|
								 /* Surprisingly, Windows takes massively more time than UNIX to write
							 | 
						|
								  * out all the entries, so we need different ITERATIONS count otherwise
							 | 
						|
								  * Windows users running the component tests may think the process has
							 | 
						|
								  * hung and kill it
							 | 
						|
								  */
							 | 
						|
								# if defined(PLATFORMSTL_OS_IS_WINDOWS)
							 | 
						|
								const size_t    LOG_ITERATIONS      =   5000;
							 | 
						|
								# else /* ? OS */
							 | 
						|
								const size_t    LOG_ITERATIONS      =   100000;
							 | 
						|
								# endif /* OS */
							 | 
						|
								const size_t    SET_PATH_DELAY      =   1000 * 1000 * 10;
							 | 
						|
								#endif /* _DEBUG */
							 | 
						|
								
							 | 
						|
								const PAN_CHAR_T LOG_FILE_NAME[]    =   PSTR("test.component.be.file.threading.log");
							 | 
						|
								
							 | 
						|
								/* /////////////////////////////////////////////////////////////////////////
							 | 
						|
								 * Globals
							 | 
						|
								 */
							 | 
						|
								
							 | 
						|
								#if defined(PLATFORMSTL_OS_IS_UNIX)
							 | 
						|
								static pthread_mutex_t  s_mx            =   PTHREAD_MUTEX_INITIALIZER;
							 | 
						|
								static pthread_cond_t   s_cv            =   PTHREAD_COND_INITIALIZER;
							 | 
						|
								static int              s_activeThreads =   0;
							 | 
						|
								#endif /* OS */
							 | 
						|
								
							 | 
						|
								static int              s_showNotices   =   true;
							 | 
						|
								
							 | 
						|
								extern "C" const PAN_CHAR_T PANTHEIOS_FE_PROCESS_IDENTITY[]    =   PSTR("test.component.be.file.threading");
							 | 
						|
								
							 | 
						|
								/* /////////////////////////////////////////////////////////////////////////
							 | 
						|
								 * Typedefs
							 | 
						|
								 */
							 | 
						|
								
							 | 
						|
								#if defined(PLATFORMSTL_OS_IS_UNIX)
							 | 
						|
								
							 | 
						|
								typedef pthread_t   thread_handle_t;
							 | 
						|
								
							 | 
						|
								#elif defined(PLATFORMSTL_OS_IS_WINDOWS)
							 | 
						|
								
							 | 
						|
								typedef HANDLE      thread_handle_t;
							 | 
						|
								
							 | 
						|
								#else /* ? OS */
							 | 
						|
								
							 | 
						|
								# error Operating system not discriminated
							 | 
						|
								
							 | 
						|
								#endif /* OS */
							 | 
						|
								
							 | 
						|
								typedef platformstl::filesystem_traits<PAN_CHAR_T>  fs_traits_t;
							 | 
						|
								typedef platformstl::basic_file_lines<PAN_CHAR_T>   lines_t;
							 | 
						|
								typedef stlsoft::basic_string_view<PAN_CHAR_T>          string_view_t;
							 | 
						|
								
							 | 
						|
								/* /////////////////////////////////////////////////////////////////////////
							 | 
						|
								 * Forward declarations
							 | 
						|
								 */
							 | 
						|
								
							 | 
						|
								#if defined(PLATFORMSTL_OS_IS_UNIX)
							 | 
						|
								
							 | 
						|
								static void* thread_proc(void*);
							 | 
						|
								
							 | 
						|
								#elif defined(PLATFORMSTL_OS_IS_WINDOWS)
							 | 
						|
								
							 | 
						|
								static DWORD WINAPI thread_proc(void*);
							 | 
						|
								
							 | 
						|
								#else /* ? OS */
							 | 
						|
								
							 | 
						|
								# error Operating system not discriminated
							 | 
						|
								
							 | 
						|
								#endif /* OS */
							 | 
						|
								
							 | 
						|
								/* /////////////////////////////////////////////////////////////////////////
							 | 
						|
								 * Pantheios configuration
							 | 
						|
								 */
							 | 
						|
								
							 | 
						|
								enum
							 | 
						|
								{
							 | 
						|
								    beid_console    =   1,
							 | 
						|
								    beid_file       =   2,
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								extern "C"
							 | 
						|
								{
							 | 
						|
								
							 | 
						|
								pan_fe_N_t PAN_FE_N_SEVERITY_CEILINGS[] =
							 | 
						|
								{
							 | 
						|
								#ifdef _DEBUG
							 | 
						|
								    { beid_console, PANTHEIOS_SEV_NOTICE },
							 | 
						|
								#else /* ? _DEBUG */
							 | 
						|
								    { beid_console, PANTHEIOS_SEV_NOTICE },
							 | 
						|
								#endif /* _DEBUG */
							 | 
						|
								    { beid_file, PANTHEIOS_SEV_INFORMATIONAL },
							 | 
						|
								
							 | 
						|
								    PANTHEIOS_FE_N_TERMINATOR_ENTRY(PANTHEIOS_SEV_INFORMATIONAL)
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								pan_be_N_t PAN_BE_N_BACKEND_LIST[] =
							 | 
						|
								{
							 | 
						|
								    PANTHEIOS_BE_N_STDFORM_ENTRY(beid_console, pantheios_be_console, PANTHEIOS_BE_N_F_IGNORE_NONMATCHED_CUSTOM28_ID),
							 | 
						|
								    PANTHEIOS_BE_N_STDFORM_ENTRY(beid_file, pantheios_be_file, PANTHEIOS_BE_N_F_ID_MUST_MATCH_CUSTOM28),
							 | 
						|
								
							 | 
						|
								    PANTHEIOS_BE_N_TERMINATOR_ENTRY
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								} // extern "C"
							 | 
						|
								
							 | 
						|
								/* ////////////////////////////////////////////////////////////////////// */
							 | 
						|
								
							 | 
						|
								static int main_(int /*argc*/, char** /*argv*/)
							 | 
						|
								{
							 | 
						|
								    thread_handle_t   threads[32];
							 | 
						|
								
							 | 
						|
								    pan::log_INFORMATIONAL(PSTR("main(): creating "), pan::integer(STLSOFT_NUM_ELEMENTS(threads)), PSTR(" threads"));
							 | 
						|
								
							 | 
						|
								    { for(size_t i = 0; i < STLSOFT_NUM_ELEMENTS(threads); ++i)
							 | 
						|
								    {
							 | 
						|
								        void* arg = NULL;
							 | 
						|
								
							 | 
						|
								#if defined(PLATFORMSTL_OS_IS_UNIX)
							 | 
						|
								
							 | 
						|
								        pthread_mutex_lock(&s_mx);
							 | 
						|
								
							 | 
						|
								        if(0 != pthread_create(&threads[i], NULL, thread_proc, arg))
							 | 
						|
								        {
							 | 
						|
								            pan::log_ALERT(PSTR("Failed to create thread "), pan::integer(i));
							 | 
						|
								
							 | 
						|
								            pthread_mutex_unlock(&s_mx);
							 | 
						|
								
							 | 
						|
								            return EXIT_FAILURE;
							 | 
						|
								        }
							 | 
						|
								        else
							 | 
						|
								        {
							 | 
						|
								            pthread_detach(threads[i]);
							 | 
						|
								            ++s_activeThreads;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        pthread_mutex_unlock(&s_mx);
							 | 
						|
								#elif defined(PLATFORMSTL_OS_IS_WINDOWS)
							 | 
						|
								
							 | 
						|
								        // NOTE: We are calling the Windows API function CreateThread()
							 | 
						|
								        // directly, rather than going through beginthreadex() (or
							 | 
						|
								        // equivalent), which is not the correct thing to do in a real
							 | 
						|
								        // program, as CRT resources can be leaked.
							 | 
						|
								        //
							 | 
						|
								        // We do it this way in this case simply for portability of the
							 | 
						|
								        // test program
							 | 
						|
								
							 | 
						|
								        DWORD   threadId;
							 | 
						|
								
							 | 
						|
								        threads[i] = CreateThread(NULL, 0, thread_proc, arg, 0, &threadId);
							 | 
						|
								
							 | 
						|
								        if(NULL == threads[i])
							 | 
						|
								        {
							 | 
						|
								            winstl::error_desc  err;
							 | 
						|
								
							 | 
						|
								            pan::log_ALERT(PSTR("Failed to create thread "), pan::integer(i), PSTR(": "), err);
							 | 
						|
								
							 | 
						|
								            return EXIT_FAILURE;
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								#else /* ? OS */
							 | 
						|
								# error Operating system not discriminated
							 | 
						|
								#endif /* 0 */
							 | 
						|
								    }}
							 | 
						|
								
							 | 
						|
								    s_showNotices &&
							 | 
						|
								    pan::log_NOTICE(PSTR("main(): all "), pan::integer(STLSOFT_NUM_ELEMENTS(threads)), PSTR(" threads started"));
							 | 
						|
								
							 | 
						|
								    platformstl::micro_sleep(SET_PATH_DELAY);
							 | 
						|
								
							 | 
						|
								    s_showNotices &&
							 | 
						|
								    pan::log_NOTICE(PSTR("main(): setting log file path"));
							 | 
						|
								
							 | 
						|
								    pantheios_be_file_setFilePath(LOG_FILE_NAME, PANTHEIOS_BE_FILE_F_TRUNCATE, PANTHEIOS_BE_FILE_F_TRUNCATE, 0);
							 | 
						|
								
							 | 
						|
								    s_showNotices &&
							 | 
						|
								    pan::log_NOTICE(PSTR("main(): waiting for threads to complete; this could take several minutes"));
							 | 
						|
								
							 | 
						|
								#if defined(PLATFORMSTL_OS_IS_UNIX)
							 | 
						|
								
							 | 
						|
								    for(;;)
							 | 
						|
								    {
							 | 
						|
								        pthread_mutex_lock(&s_mx);
							 | 
						|
								        if(0 == s_activeThreads)
							 | 
						|
								        {
							 | 
						|
								            pthread_mutex_unlock(&s_mx);
							 | 
						|
								            break;
							 | 
						|
								        }
							 | 
						|
								        else
							 | 
						|
								        {
							 | 
						|
								            pthread_cond_wait(&s_cv, &s_mx);
							 | 
						|
								        }
							 | 
						|
								        pthread_mutex_unlock(&s_mx);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								#elif defined(PLATFORMSTL_OS_IS_WINDOWS)
							 | 
						|
								
							 | 
						|
								    ::WaitForMultipleObjects(STLSOFT_NUM_ELEMENTS(threads), &threads[0], true, INFINITE);
							 | 
						|
								
							 | 
						|
								#else /* ? OS */
							 | 
						|
								# error Operating system not discriminated
							 | 
						|
								#endif /* 0 */
							 | 
						|
								
							 | 
						|
								    s_showNotices &&
							 | 
						|
								    pan::log_NOTICE(PSTR("main(): all "), pan::integer(STLSOFT_NUM_ELEMENTS(threads)), PSTR(" threads completed"));
							 | 
						|
								
							 | 
						|
								    pantheios_be_file_setFilePath(NULL);
							 | 
						|
								
							 | 
						|
								    int retVal = EXIT_SUCCESS;
							 | 
						|
								
							 | 
						|
								    lines_t lines(LOG_FILE_NAME);
							 | 
						|
								
							 | 
						|
								    { for(size_t i = 0; i != lines.size(); ++i)
							 | 
						|
								    {
							 | 
						|
								        lines_t::value_type const&  line = lines[i];
							 | 
						|
								
							 | 
						|
								        string_view_t               scratch1;
							 | 
						|
								        string_view_t               scratch2;
							 | 
						|
								                                    
							 | 
						|
								        string_view_t               prefix;
							 | 
						|
								        string_view_t               left;
							 | 
						|
								        string_view_t               middle;
							 | 
						|
								        string_view_t               right;
							 | 
						|
								
							 | 
						|
								        if( !stlsoft::split(line, PSTR('|'), prefix, scratch1) ||
							 | 
						|
								            !stlsoft::split(scratch1, PSTR('|'), left, scratch2) ||
							 | 
						|
								            !stlsoft::split(scratch2, PSTR('|'), middle, right))
							 | 
						|
								        {
							 | 
						|
								            pan::log_CRITICAL(PSTR("line does not have required format: ["), pan::integer(i), PSTR(": "), line, PSTR("]"));
							 | 
						|
								
							 | 
						|
								            retVal = EXIT_FAILURE;
							 | 
						|
								        }
							 | 
						|
								        else
							 | 
						|
								        {
							 | 
						|
								            if(left != right)
							 | 
						|
								            {
							 | 
						|
								                pan::log_CRITICAL(PSTR("line prefix and suffix do not match: ["), pan::integer(i), PSTR(": "), line, PSTR("]"));
							 | 
						|
								
							 | 
						|
								                retVal = EXIT_FAILURE;
							 | 
						|
								            }
							 | 
						|
								        }
							 | 
						|
								    }}
							 | 
						|
								
							 | 
						|
								    if(EXIT_SUCCESS == retVal)
							 | 
						|
								    {
							 | 
						|
								        s_showNotices &&
							 | 
						|
								        pan::log_NOTICE(PSTR("all lines logged to file correctly"));
							 | 
						|
								    }
							 | 
						|
								    else
							 | 
						|
								    {
							 | 
						|
								        pan::log_CRITICAL(PSTR("multi-threaded use of be.file has been defective; please report to the Pantheios project"));
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    return retVal;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								#ifdef USE_MSC_VER_CRT_MEM_CHECKS
							 | 
						|
								int main__(int argc, char** argv)
							 | 
						|
								{
							 | 
						|
								    _CrtMemState memState;
							 | 
						|
								
							 | 
						|
								    _CrtMemCheckpoint(&memState);
							 | 
						|
								
							 | 
						|
								    int r = main_(argc, argv);
							 | 
						|
								
							 | 
						|
								    _CrtMemDumpAllObjectsSince(&memState);
							 | 
						|
								
							 | 
						|
								    return r;
							 | 
						|
								}
							 | 
						|
								#else /* ? USE_MSC_VER_CRT_MEM_CHECKS */
							 | 
						|
								# define main__     main_
							 | 
						|
								#endif /* USE_MSC_VER_CRT_MEM_CHECKS */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								int main(int argc, char** argv)
							 | 
						|
								{
							 | 
						|
								    if(2 == argc)
							 | 
						|
								    {
							 | 
						|
								        char const* arg = argv[1];
							 | 
						|
								
							 | 
						|
								        if(0 == ::strncmp(arg, "--verbosity=", 12))
							 | 
						|
								        {
							 | 
						|
								            int verbosity = atoi(arg + 12);
							 | 
						|
								
							 | 
						|
								            if(verbosity < 0)
							 | 
						|
								            {
							 | 
						|
								                verbosity = 0;
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            switch(verbosity)
							 | 
						|
								            {
							 | 
						|
								                case    0:
							 | 
						|
								                case    1:
							 | 
						|
								                    s_showNotices = false;
							 | 
						|
								                    break;
							 | 
						|
								                default:
							 | 
						|
								                    s_showNotices = true;
							 | 
						|
								                    break;
							 | 
						|
								            }
							 | 
						|
								        }
							 | 
						|
								        else
							 | 
						|
								        {
							 | 
						|
								            fprintf(stderr, "unrecognised argument: '%s'\n", arg);
							 | 
						|
								
							 | 
						|
								            return EXIT_FAILURE;
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								#ifdef STLSOFT_CF_EXCEPTION_SUPPORT
							 | 
						|
								    try
							 | 
						|
								    {
							 | 
						|
								#endif /* !STLSOFT_CF_EXCEPTION_SUPPORT */
							 | 
						|
								
							 | 
						|
								        int r = main_(argc, argv);
							 | 
						|
								
							 | 
						|
								        fs_traits_t::unlink_file(LOG_FILE_NAME);
							 | 
						|
								
							 | 
						|
								        return r;
							 | 
						|
								
							 | 
						|
								#ifdef STLSOFT_CF_EXCEPTION_SUPPORT
							 | 
						|
								    }
							 | 
						|
								    catch(std::exception& x)
							 | 
						|
								    {
							 | 
						|
								        pan::log_ALERT(PSTR("Unexpected general error: "), pantheios::exception(x), PSTR(". Application terminating"));
							 | 
						|
								    }
							 | 
						|
								    catch(...)
							 | 
						|
								    {
							 | 
						|
								        pan::logputs(pan::emergency, PSTR("Unhandled unknown error"));
							 | 
						|
								    }
							 | 
						|
								#endif /* !STLSOFT_CF_EXCEPTION_SUPPORT */
							 | 
						|
								
							 | 
						|
								    fs_traits_t::unlink_file(LOG_FILE_NAME);
							 | 
						|
								
							 | 
						|
								    return EXIT_FAILURE;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								/* ////////////////////////////////////////////////////////////////////// */
							 | 
						|
								
							 | 
						|
								#if defined(PLATFORMSTL_OS_IS_UNIX)
							 | 
						|
								static void* thread_proc(void*)
							 | 
						|
								#elif defined(PLATFORMSTL_OS_IS_WINDOWS)
							 | 
						|
								static DWORD WINAPI thread_proc(void*)
							 | 
						|
								#endif /* OS */
							 | 
						|
								{
							 | 
						|
								#if defined(PLATFORMSTL_OS_IS_UNIX)
							 | 
						|
								    thread_handle_t self = pthread_self();
							 | 
						|
								#elif defined(PLATFORMSTL_OS_IS_WINDOWS)
							 | 
						|
								    thread_handle_t self = GetCurrentThread();
							 | 
						|
								#endif /* OS */
							 | 
						|
								
							 | 
						|
								    pan::log_INFORMATIONAL(PSTR("thread_proc("), pan::blob(&self, sizeof(self)), PSTR("): entering"));
							 | 
						|
								
							 | 
						|
								    // TODO: Do some threading stuff
							 | 
						|
								
							 | 
						|
								    { for(size_t i = 0; i != LOG_ITERATIONS; ++i)
							 | 
						|
								    {
							 | 
						|
								        pan::log(pan::informational(beid_file), PSTR("|"), pan::integer(i), PSTR("|"), PSTR("this is"), PSTR(" "), PSTR("multipart log "), PSTR("statement"), PSTR("|"), pan::integer(i));
							 | 
						|
								    }}
							 | 
						|
								
							 | 
						|
								#if defined(PLATFORMSTL_OS_IS_UNIX)
							 | 
						|
								    pthread_mutex_lock(&s_mx);
							 | 
						|
								    --s_activeThreads;
							 | 
						|
								    pthread_cond_signal(&s_cv);
							 | 
						|
								    pthread_mutex_unlock(&s_mx);
							 | 
						|
								#endif /* OS */
							 | 
						|
								
							 | 
						|
								    pan::log_INFORMATIONAL(PSTR("thread_proc("), pan::blob(&self, sizeof(self)), PSTR("): exiting"));
							 | 
						|
								
							 | 
						|
								    return 0;
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								/* ////////////////////////////////////////////////////////////////////// */
							 | 
						|
								
							 | 
						|
								#if defined(PLATFORMSTL_OS_IS_UNIX) && \
							 | 
						|
								    defined(_WIN32) && \
							 | 
						|
								    defined(_STLSOFT_FORCE_ANY_COMPILER)
							 | 
						|
								# include <windows.h>
							 | 
						|
								extern "C" void syslog(char const* s)
							 | 
						|
								{
							 | 
						|
								    OutputDebugStringA(s);
							 | 
						|
								}
							 | 
						|
								#endif
							 | 
						|
								
							 | 
						|
								/* ///////////////////////////// end of file //////////////////////////// */
							 |