complement-svn Mailing List for Complement (Page 7)
Status: Pre-Alpha
Brought to you by:
complement
You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(61) |
Nov
(76) |
Dec
(39) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
(33) |
Feb
(41) |
Mar
(16) |
Apr
|
May
(22) |
Jun
(14) |
Jul
(64) |
Aug
(60) |
Sep
(35) |
Oct
(34) |
Nov
(10) |
Dec
(5) |
2008 |
Jan
(4) |
Feb
(24) |
Mar
(10) |
Apr
(30) |
May
(15) |
Jun
(50) |
Jul
(20) |
Aug
(7) |
Sep
(8) |
Oct
(10) |
Nov
|
Dec
|
From: <com...@us...> - 2008-02-28 18:15:43
|
Revision: 1828 http://complement.svn.sourceforge.net/complement/?rev=1828&view=rev Author: complement Date: 2008-02-28 10:15:40 -0800 (Thu, 28 Feb 2008) Log Message: ----------- branch for sockios buf, common poll Added Paths: ----------- branches/complement-sockios/ Copied: branches/complement-sockios (from rev 1827, trunk/complement) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-02-28 13:15:40
|
Revision: 1827 http://complement.svn.sourceforge.net/complement/?rev=1827&view=rev Author: complement Date: 2008-02-28 05:15:08 -0800 (Thu, 28 Feb 2008) Log Message: ----------- merged into trunk Removed Paths: ------------- branches/wg21-thread/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-02-28 11:16:26
|
Revision: 1826 http://complement.svn.sourceforge.net/complement/?rev=1826&view=rev Author: complement Date: 2008-02-28 03:16:23 -0800 (Thu, 28 Feb 2008) Log Message: ----------- move findhost and iface list utilities into separate files; libsockios: Version 1.14.2. Modified Paths: -------------- trunk/complement/explore/include/sockios/sockstream trunk/complement/explore/include/sockios/sockstream.cc trunk/complement/explore/lib/sockios/ChangeLog trunk/complement/explore/lib/sockios/Makefile.inc trunk/complement/explore/lib/sockios/_sockstream.cc Added Paths: ----------- trunk/complement/explore/include/sockios/netinfo.h trunk/complement/explore/lib/sockios/netinfo.cc Copied: trunk/complement/explore/include/sockios/netinfo.h (from rev 1817, trunk/complement/explore/include/sockios/sockstream) =================================================================== --- trunk/complement/explore/include/sockios/netinfo.h (rev 0) +++ trunk/complement/explore/include/sockios/netinfo.h 2008-02-28 11:16:23 UTC (rev 1826) @@ -0,0 +1,268 @@ +// -*- C++ -*- Time-stamp: <07/09/06 23:42:19 ptr> + +/* + * Copyright (c) 1997-1999, 2002, 2003, 2005-2008 + * Petr Ovtchenkov + * + * Portion Copyright (c) 1999-2001 + * Parallel Graphics Ltd. + * + * Licensed under the Academic Free License version 3.0 + * + */ + +#ifndef __SOCKIOS_NETINFO_H +#define __SOCKIOS_NETINFO_H + +#ifndef __config_feature_h +#include <config/feature.h> +#endif + +#ifdef __FIT_NONREENTRANT +extern "C" int x_getaddrinfo(const char *, const char *, const struct addrinfo *, struct addrinfo **); +extern "C" void x_freeaddrinfo( struct addrinfo * ); +extern "C" int x_res_search(const char *, int, int, unsigned char *, int); +extern "C" int x_res_init(void); +#endif + +#include <netdb.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> +#include <sys/ioctl.h> +#include <net/if.h> + +#include <string> +#include <stdexcept> + +#ifdef WIN32 +# include <winsock2.h> +#else // WIN32 +# include <unistd.h> +# include <sys/types.h> +# if defined(__hpux) && !defined(_INCLUDE_XOPEN_SOURCE_EXTENDED) +# define _INCLUDE_XOPEN_SOURCE_EXTENDED +# endif +# include <sys/socket.h> +# if !defined(__UCLIBC__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) +# include <stropts.h> +# endif +# ifdef __sun +# include <sys/conf.h> +# endif +# include <netinet/in.h> +# include <arpa/inet.h> +# include <netdb.h> +# ifdef __hpux +// # ifndef socklen_t // HP-UX 10.01 +// typedef int socklen_t; +// # endif +# endif +# include <cerrno> +#endif // !WIN32 + +#ifdef STLPORT +_STLP_BEGIN_NAMESPACE +#else +namespace std { +#endif + +in_addr findhost( const char *hostname ) throw( std::domain_error ); +std::string hostname( unsigned long inet_addr ); +std::string hostname(); + +int service( const char *name, const char *proto ) throw( std::domain_error ); +std::string service( int port, const char *proto ) throw( std::domain_error ); + +/* + * Expected host name, return (via back insert iterator) + * all IPs (in_addr) for specified host name; nothing will be added in case of + * failure. + */ +template <class BackInsertIterator> +void gethostaddr( const char *hostname, BackInsertIterator bi ) +{ + int _errno = 0; + +#ifndef __FIT_GETHOSTBYADDR + hostent _host; +# ifndef __hpux + char tmpbuf[4096]; +# else // __hpux + hostent_data tmpbuf; +# endif // __hpux +# ifdef __linux + hostent *host = 0; + gethostbyname_r( hostname, &_host, tmpbuf, 4096, &host, &_errno ); +# elif defined(__hpux) + _errno = gethostbyname_r( hostname, &_host, &tmpbuf ); + hostent *host = &_host; +# elif defined(__sun) + hostent *host = gethostbyname_r( hostname, &_host, tmpbuf, 4096, &_errno ); +# else // !__linux !__hpux !__sun +# error "Check port of gethostbyname_r" +# endif // __linux __hpux __sun +#else // __FIT_GETHOSTBYADDR + hostent *host = gethostbyname( hostname ); +# ifdef WIN32 + if ( host == 0 ) { + _errno = WSAGetLastError(); + + // specific to Wins only: + // cool M$ can't resolve IP address in gethostbyname, try once more + // via inet_addr() and gethostbyaddr() + // Returned _errno depend upon WinSock version, and applied patches, + // with some of it even gethostbyname may be succeed. + if ( _errno == WSAHOST_NOT_FOUND || _errno == WSATRY_AGAIN ) { + unsigned long ipaddr = ::inet_addr( hostname ); + if ( ipaddr != INADDR_NONE ) { + host = gethostbyaddr( (const char *)&ipaddr, sizeof(ipaddr), AF_INET ); + if ( host != 0 ) { // Oh, that's was IP indeed... + memcpy( (char *)&inet, (char *)host->h_addr, host->h_length ); + WSASetLastError( 0 ); // clear error + _errno = 0; + } else { + _errno = WSAGetLastError(); + } + } + } + } +# endif // WIN32 +#endif // __FIT_GETHOSTBYADDR + + if ( host != 0 && host->h_length == sizeof(in_addr) ) { + for ( char **_inet = host->h_addr_list; *_inet != 0; ++_inet ) { + *bi++ = *((in_addr *)*_inet); + } + } +} + +/* + * Expected host name, return (via back insert iterator) + * all sockaddr for specified host name; nothing will be added in case of + * failure. (Alternative implementation to gethostaddr above; it most + * useful on systems without reentrant gethostbyname_r, but that has + * reentrant getaddrinfo, like FreeBSD >= 5.3) + */ +template <class BackInsertIterator> +void gethostaddr2( const char *hostname, BackInsertIterator bi ) +{ + // addrinfo hints; + addrinfo *hosts_list = 0; + +#ifndef __FIT_NONREENTRANT + int _errno = getaddrinfo( hostname, 0, 0, &hosts_list ); +#else + int _errno = x_getaddrinfo( hostname, 0, 0, &hosts_list ); +#endif + if ( _errno == 0 ) { + addrinfo *host = hosts_list; + if ( host != 0 && host->ai_addr != 0 ) { + while ( host != 0 ) { + // *bi++ = ((in_addr *)host->ai_addr->sa_data)->s_addr; + *bi++ = *host->ai_addr; + host = host->ai_next; + } + } + } + if ( hosts_list != 0 ) { +#ifndef __FIT_NONREENTRANT + freeaddrinfo( hosts_list ); +#else + x_freeaddrinfo( hosts_list ); +#endif + } +} + +struct net_iface +{ + net_iface() + { } + + net_iface( const char *nm, unsigned f, const sockaddr& address ) : + name( nm ), + flags( f ) + { + addr.any = address; + } + + std::string name; + union { + sockaddr_in inet; + sockaddr any; + } addr; + // struct in_addr mask; + unsigned flags; +}; + +template <class C> +void get_ifaces( C& lst ) +{ + int sock = socket(AF_INET, SOCK_DGRAM, 0); + struct ifconf ifc; + char st_buf[100 * sizeof(struct ifreq)]; + char *buf = 0; + int len = sizeof( st_buf ); + ifc.ifc_len = len; + ifc.ifc_buf = st_buf; + for ( ; ; ) { + if ( ioctl(sock, SIOCGIFCONF, &ifc) < 0 ) { + if ( errno != EINVAL ) { + if ( ifc.ifc_buf != st_buf ) { + free( ifc.ifc_buf ); + } + close( sock ); + throw std::runtime_error( std::string("SIOCGIFCONF ioctl error getting list of interfaces") ); + } + } else { + if ( ifc.ifc_len < sizeof(struct ifreq) ) { + if ( ifc.ifc_buf != st_buf ) { + free( ifc.ifc_buf ); + } + close( sock ); + throw std::runtime_error( std::string("SIOCGIFCONF ioctl gave too small return buffer") ); + } + } + if ( ifc.ifc_len >= len ) { + len = ifc.ifc_len + 10 * sizeof(struct ifreq); + if ( ifc.ifc_buf != st_buf ) { + free( ifc.ifc_buf ); + } + ifc.ifc_buf = (char *)malloc( len ); + ifc.ifc_len = len; + } else { + break; + } + } + struct ifreq* ifr = (struct ifreq *) ifc.ifc_req; + struct ifreq* last = (struct ifreq *) ((char *) ifr + ifc.ifc_len); + struct ifreq ifrflags; + while ( ifr < last ) { + memset(&ifrflags, 0, sizeof(ifrflags) ); + strncpy( ifrflags.ifr_name, ifr->ifr_name, sizeof( ifrflags.ifr_name ) ); + if ( ioctl(sock, SIOCGIFFLAGS, (char *)&ifrflags) < 0 ) { + if ( errno != ENXIO ) { + if ( ifc.ifc_buf != st_buf ) { + free( ifc.ifc_buf ); + } + close( sock ); + throw std::runtime_error( std::string("SIOCGIFFLAGS error getting flags for interface") ); + } + } + lst.push_back( net_iface( ifr->ifr_name, ifrflags.ifr_flags, ifr->ifr_addr ) ); + ifr = (struct ifreq *) ((char *) ifr + sizeof(struct ifreq)); + } + + if ( ifc.ifc_buf != st_buf ) { + free( ifc.ifc_buf ); + } + close( sock ); +} + +#ifdef STLPORT +_STLP_END_NAMESPACE +#else +} // namespace std +#endif + +#endif // __SOCKSIOS_NETINFO_H Modified: trunk/complement/explore/include/sockios/sockstream =================================================================== --- trunk/complement/explore/include/sockios/sockstream 2008-02-28 11:15:13 UTC (rev 1825) +++ trunk/complement/explore/include/sockios/sockstream 2008-02-28 11:16:23 UTC (rev 1826) @@ -26,19 +26,8 @@ #include <mt/xmt.h> #endif -#ifdef __FIT_NONREENTRANT -extern "C" int x_getaddrinfo(const char *, const char *, const struct addrinfo *, struct addrinfo **); -extern "C" void x_freeaddrinfo( struct addrinfo * ); -extern "C" int x_res_search(const char *, int, int, unsigned char *, int); -extern "C" int x_res_init(void); -#endif - #include <netdb.h> #include <netinet/in.h> -#include <arpa/nameser.h> -#include <resolv.h> -#include <sys/ioctl.h> -#include <net/if.h> #include <iosfwd> #include <ios> @@ -73,204 +62,14 @@ # include <cerrno> #endif // !WIN32 +#include <sockios/netinfo.h> + #ifdef STLPORT _STLP_BEGIN_NAMESPACE #else namespace std { #endif -in_addr findhost( const char *hostname ) throw( std::domain_error ); -std::string hostname( unsigned long inet_addr ); -std::string hostname(); - -int service( const char *name, const char *proto ) throw( std::domain_error ); -std::string service( int port, const char *proto ) throw( std::domain_error ); - -/* - * Expected host name, return (via back insert iterator) - * all IPs (in_addr) for specified host name; nothing will be added in case of - * failure. - */ -template <class BackInsertIterator> -void gethostaddr( const char *hostname, BackInsertIterator bi ) -{ - int _errno = 0; - -#ifndef __FIT_GETHOSTBYADDR - hostent _host; -# ifndef __hpux - char tmpbuf[4096]; -# else // __hpux - hostent_data tmpbuf; -# endif // __hpux -# ifdef __linux - hostent *host = 0; - gethostbyname_r( hostname, &_host, tmpbuf, 4096, &host, &_errno ); -# elif defined(__hpux) - _errno = gethostbyname_r( hostname, &_host, &tmpbuf ); - hostent *host = &_host; -# elif defined(__sun) - hostent *host = gethostbyname_r( hostname, &_host, tmpbuf, 4096, &_errno ); -# else // !__linux !__hpux !__sun -# error "Check port of gethostbyname_r" -# endif // __linux __hpux __sun -#else // __FIT_GETHOSTBYADDR - hostent *host = gethostbyname( hostname ); -# ifdef WIN32 - if ( host == 0 ) { - _errno = WSAGetLastError(); - - // specific to Wins only: - // cool M$ can't resolve IP address in gethostbyname, try once more - // via inet_addr() and gethostbyaddr() - // Returned _errno depend upon WinSock version, and applied patches, - // with some of it even gethostbyname may be succeed. - if ( _errno == WSAHOST_NOT_FOUND || _errno == WSATRY_AGAIN ) { - unsigned long ipaddr = ::inet_addr( hostname ); - if ( ipaddr != INADDR_NONE ) { - host = gethostbyaddr( (const char *)&ipaddr, sizeof(ipaddr), AF_INET ); - if ( host != 0 ) { // Oh, that's was IP indeed... - memcpy( (char *)&inet, (char *)host->h_addr, host->h_length ); - WSASetLastError( 0 ); // clear error - _errno = 0; - } else { - _errno = WSAGetLastError(); - } - } - } - } -# endif // WIN32 -#endif // __FIT_GETHOSTBYADDR - - if ( host != 0 && host->h_length == sizeof(in_addr) ) { - for ( char **_inet = host->h_addr_list; *_inet != 0; ++_inet ) { - *bi++ = *((in_addr *)*_inet); - } - } -} - -/* - * Expected host name, return (via back insert iterator) - * all sockaddr for specified host name; nothing will be added in case of - * failure. (Alternative implementation to gethostaddr above; it most - * useful on systems without reentrant gethostbyname_r, but that has - * reentrant getaddrinfo, like FreeBSD >= 5.3) - */ -template <class BackInsertIterator> -void gethostaddr2( const char *hostname, BackInsertIterator bi ) -{ - // addrinfo hints; - addrinfo *hosts_list = 0; - -#ifndef __FIT_NONREENTRANT - int _errno = getaddrinfo( hostname, 0, 0, &hosts_list ); -#else - int _errno = x_getaddrinfo( hostname, 0, 0, &hosts_list ); -#endif - if ( _errno == 0 ) { - addrinfo *host = hosts_list; - if ( host != 0 && host->ai_addr != 0 ) { - while ( host != 0 ) { - // *bi++ = ((in_addr *)host->ai_addr->sa_data)->s_addr; - *bi++ = *host->ai_addr; - host = host->ai_next; - } - } - } - if ( hosts_list != 0 ) { -#ifndef __FIT_NONREENTRANT - freeaddrinfo( hosts_list ); -#else - x_freeaddrinfo( hosts_list ); -#endif - } -} - -struct net_iface -{ - net_iface() - { } - - net_iface( const char *nm, unsigned f, const sockaddr& address ) : - name( nm ), - flags( f ) - { - addr.any = address; - } - - std::string name; - union { - sockaddr_in inet; - sockaddr any; - } addr; - // struct in_addr mask; - unsigned flags; -}; - -template <class C> -void get_ifaces( C& lst ) -{ - int sock = socket(AF_INET, SOCK_DGRAM, 0); - struct ifconf ifc; - char st_buf[100 * sizeof(struct ifreq)]; - char *buf = 0; - int len = sizeof( st_buf ); - ifc.ifc_len = len; - ifc.ifc_buf = st_buf; - for ( ; ; ) { - if ( ioctl(sock, SIOCGIFCONF, &ifc) < 0 ) { - if ( errno != EINVAL ) { - if ( ifc.ifc_buf != st_buf ) { - free( ifc.ifc_buf ); - } - close( sock ); - throw std::runtime_error( std::string("SIOCGIFCONF ioctl error getting list of interfaces") ); - } - } else { - if ( ifc.ifc_len < sizeof(struct ifreq) ) { - if ( ifc.ifc_buf != st_buf ) { - free( ifc.ifc_buf ); - } - close( sock ); - throw std::runtime_error( std::string("SIOCGIFCONF ioctl gave too small return buffer") ); - } - } - if ( ifc.ifc_len >= len ) { - len = ifc.ifc_len + 10 * sizeof(struct ifreq); - if ( ifc.ifc_buf != st_buf ) { - free( ifc.ifc_buf ); - } - ifc.ifc_buf = (char *)malloc( len ); - ifc.ifc_len = len; - } else { - break; - } - } - struct ifreq* ifr = (struct ifreq *) ifc.ifc_req; - struct ifreq* last = (struct ifreq *) ((char *) ifr + ifc.ifc_len); - struct ifreq ifrflags; - while ( ifr < last ) { - memset(&ifrflags, 0, sizeof(ifrflags) ); - strncpy( ifrflags.ifr_name, ifr->ifr_name, sizeof( ifrflags.ifr_name ) ); - if ( ioctl(sock, SIOCGIFFLAGS, (char *)&ifrflags) < 0 ) { - if ( errno != ENXIO ) { - if ( ifc.ifc_buf != st_buf ) { - free( ifc.ifc_buf ); - } - close( sock ); - throw std::runtime_error( std::string("SIOCGIFFLAGS error getting flags for interface") ); - } - } - lst.push_back( net_iface( ifr->ifr_name, ifrflags.ifr_flags, ifr->ifr_addr ) ); - ifr = (struct ifreq *) ((char *) ifr + sizeof(struct ifreq)); - } - - if ( ifc.ifc_buf != st_buf ) { - free( ifc.ifc_buf ); - } - close( sock ); -} - class sock_base { public: Modified: trunk/complement/explore/include/sockios/sockstream.cc =================================================================== --- trunk/complement/explore/include/sockios/sockstream.cc 2008-02-28 11:15:13 UTC (rev 1825) +++ trunk/complement/explore/include/sockios/sockstream.cc 2008-02-28 11:16:23 UTC (rev 1826) @@ -1,7 +1,7 @@ // -*- C++ -*- Time-stamp: <07/09/06 23:48:33 ptr> /* - * Copyright (c) 1997-1999, 2002, 2003, 2005-2007 + * Copyright (c) 1997-1999, 2002, 2003, 2005-2008 * Petr Ovtchenkov * * Portion Copyright (c) 1999-2001 @@ -11,6 +11,8 @@ * */ +#include <sockios/netinfo.h> + #ifdef __unix extern "C" int nanosleep(const struct timespec *, struct timespec *); #endif Modified: trunk/complement/explore/lib/sockios/ChangeLog =================================================================== --- trunk/complement/explore/lib/sockios/ChangeLog 2008-02-28 11:15:13 UTC (rev 1825) +++ trunk/complement/explore/lib/sockios/ChangeLog 2008-02-28 11:16:23 UTC (rev 1826) @@ -1,3 +1,11 @@ +2008-02-28 Petr Ovtchenkov <pt...@is...> + + * sochstream, _sockstream.cc, netinfo.h, netinfo.cc: + move findhost and iface list utilities into separate + files; + + * ibsockios: Version 1.14.2. + 2007-11-21 Petr Ovtchenkov <pt...@is...> * sockstream.cc: UDP require larger buffer, because it should Modified: trunk/complement/explore/lib/sockios/Makefile.inc =================================================================== --- trunk/complement/explore/lib/sockios/Makefile.inc 2008-02-28 11:15:13 UTC (rev 1825) +++ trunk/complement/explore/lib/sockios/Makefile.inc 2008-02-28 11:16:23 UTC (rev 1826) @@ -3,8 +3,8 @@ LIBNAME = sockios MAJOR = 1 MINOR = 14 -PATCH = 1 -SRC_CC = _sockstream.cc _sockmgr.cc +PATCH = 2 +SRC_CC = _sockstream.cc _sockmgr.cc netinfo.c SRC_C = freebsd/getaddrinfo.c \ freebsd/ns_parse.c \ freebsd/res_comp.c \ Modified: trunk/complement/explore/lib/sockios/_sockstream.cc =================================================================== --- trunk/complement/explore/lib/sockios/_sockstream.cc 2008-02-28 11:15:13 UTC (rev 1825) +++ trunk/complement/explore/lib/sockios/_sockstream.cc 2008-02-28 11:16:23 UTC (rev 1826) @@ -200,218 +200,3 @@ } // namespace std #endif // WIN32 - -#ifdef STLPORT -_STLP_BEGIN_NAMESPACE -#else -namespace std { -#endif - -::in_addr findhost( const char *hostname ) throw( std::domain_error ) -{ - in_addr inet; - int _errno; - -#ifndef __FIT_GETHOSTBYADDR - hostent _host; -# ifndef __hpux - char tmpbuf[1024]; -# else // __hpux - hostent_data tmpbuf; -# endif // __hpux -# ifdef __linux - hostent *host = 0; - gethostbyname_r( hostname, &_host, tmpbuf, 1024, &host, &_errno ); -# elif defined(__hpux) - _errno = gethostbyname_r( hostname, &_host, &tmpbuf ); - hostent *host = &_host; -# elif defined(__sun) - hostent *host = gethostbyname_r( hostname, &_host, tmpbuf, 1024, &_errno ); -# else // !__linux !__hpux !__sun -# error "Check port of gethostbyname_r" -# endif // __linux __hpux __sun - if ( host != 0 ) { - memcpy( (char *)&inet, (char *)host->h_addr, host->h_length ); - } -#else // __FIT_GETHOSTBYADDR - hostent *host = gethostbyname( hostname ); - if ( host != 0 ) { - memcpy( (char *)&inet, (char *)host->h_addr, host->h_length ); - } -# ifdef WIN32 - else { - _errno = WSAGetLastError(); - - // specific to Wins only: - // cool M$ can't resolve IP address in gethostbyname, try once more - // via inet_addr() and gethostbyaddr() - // Returned _errno depend upon WinSock version, and applied patches, - // with some of it even gethostbyname may be succeed. - if ( _errno == WSAHOST_NOT_FOUND || _errno == WSATRY_AGAIN ) { - unsigned long ipaddr = ::inet_addr( hostname ); - if ( ipaddr != INADDR_NONE ) { - host = gethostbyaddr( (const char *)&ipaddr, sizeof(ipaddr), AF_INET ); - if ( host != 0 ) { // Oh, that's was IP indeed... - memcpy( (char *)&inet, (char *)host->h_addr, host->h_length ); - WSASetLastError( 0 ); // clear error - _errno = 0; - } else { - _errno = WSAGetLastError(); - } - } - } - } -# endif // WIN32 -#endif // __FIT_GETHOSTBYADDR - if ( host == 0 ) { - throw std::domain_error( "host not found" ); - } - - return inet; -} - -std::string hostname( unsigned long inet_addr ) -{ - std::string _hostname; - -#ifdef __FIT_GETHOSTBYADDR - hostent *he; -#else - hostent he; -#ifndef __hpux - char tmp_buff[1024]; -#else - hostent_data tmp_buff; -#endif -# ifdef __linux - hostent *phe = 0; -# endif -#endif - int err = 0; - in_addr in; - in.s_addr = inet_addr; -#ifdef __FIT_GETHOSTBYADDR - // For Win 'he' is thread private data, so that's safe - // It's MT-safe also for HP-UX 11.00 - he = gethostbyaddr( (char *)&in.s_addr, sizeof(in_addr), AF_INET ); - if ( he != 0 ) { - _hostname = he->h_name; - } else { - _hostname = "unknown"; - } -#else // __FIT_GETHOSTBYADDR - if ( -# ifdef __sun - gethostbyaddr_r( (char *)&in.s_addr, sizeof(in_addr), AF_INET, - &he, tmp_buff, 1024, &err ) != 0 -# elif defined(__linux) - gethostbyaddr_r( (char *)&in.s_addr, sizeof(in_addr), AF_INET, - &he, tmp_buff, 1024, &phe, &err ) == 0 -# elif defined(__hpux) // reentrant variant for HP-UX before 11.00 - gethostbyaddr_r( (char *)&in.s_addr, sizeof(in_addr), AF_INET, - &he, &tmp_buff ) == 0 -# else -# error "Check port of gethostbyaddr_r" -# endif - ) - { - _hostname = he.h_name; - } else { - _hostname = "unknown"; - } -#endif // __FIT_GETHOSTBYADDR - - _hostname += " ["; - _hostname += inet_ntoa( in ); - _hostname += "]"; - - return _hostname; -} - -std::string hostname() -{ - std::string _hostname; - char tmp_buff[1024]; - - if ( gethostname( tmp_buff, 1024 ) == 0 ) { - _hostname = tmp_buff; - } else { - _hostname = "unknown"; - } - // getdomainname may be called here, but POSIX not specify such call - - return _hostname; -} - -int service( const char *name, const char *proto ) throw( std::domain_error ) -{ -#ifdef _WIN32 - typedef u_short uint16_t; -#endif -#ifndef __FIT_GETHOSTBYADDR - char tmp_buf[1024]; - struct servent se; -# ifdef __linux - struct servent *sep = 0; - if ( getservbyname_r( name, proto, &se, tmp_buf, 1024, &sep ) != 0 ) { - throw std::domain_error( "service not found" ); - } - return ntohs( uint16_t(se.s_port) ); -# endif -# ifdef __sun - if ( getservbyname_r( name, proto, &se, tmp_buf, 1024 ) == 0 ) { - throw std::domain_error( "service not found" ); - } - return ntohs( uint16_t(se.s_port) ); -# endif -#else // __FIT_GETHOSTBYADDR - struct servent *s = ::getservbyname( name, proto ); - if ( s == 0 ) { - throw std::domain_error( "service not found" ); - } - return ntohs( uint16_t(s->s_port) ); -#endif -} - -std::string service( int port, const char *proto ) throw( std::domain_error ) -{ -#ifdef _WIN32 - typedef u_short uint16_t; -#endif - std::string _servname; - - port = htons( uint16_t(port) ); - -#ifndef __FIT_GETHOSTBYADDR - char tmp_buf[1024]; - struct servent se; -# ifdef __linux - struct servent *sep = 0; - if ( getservbyport_r( port, proto, &se, tmp_buf, 1024, &sep ) != 0 ) { - throw std::domain_error( "service not found" ); - } - _servname.assign( se.s_name ); - return _servname; -# endif -# ifdef __sun - if ( getservbyport_r( port, proto, &se, tmp_buf, 1024 ) == 0 ) { - throw std::domain_error( "service not found" ); - } - _servname.assign( se.s_name ); - return _servname; -# endif -#else // __FIT_GETHOSTBYADDR - struct servent *s = ::getservbyport( port, proto ); - if ( s == 0 ) { - throw std::domain_error( "service not found" ); - } - _servname.assign( s->s_name ); - return _servname; -#endif -} - -#ifdef STLPORT -_STLP_END_NAMESPACE -#else -} // namespace std -#endif Copied: trunk/complement/explore/lib/sockios/netinfo.cc (from rev 1817, trunk/complement/explore/lib/sockios/_sockstream.cc) =================================================================== --- trunk/complement/explore/lib/sockios/netinfo.cc (rev 0) +++ trunk/complement/explore/lib/sockios/netinfo.cc 2008-02-28 11:16:23 UTC (rev 1826) @@ -0,0 +1,239 @@ +// -*- C++ -*- Time-stamp: <06/06/28 10:33:02 ptr> + +/* + * Copyright (c) 1997-1999, 2002, 2005 + * Petr Ovtchenkov + * + * Portion Copyright (c) 1999-2000 + * Parallel Graphics Ltd. + * + * Licensed under the Academic Free License Version 2.1 + * + * This material is provided "as is", with absolutely no warranty expressed + * or implied. Any use is at your own risk. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. + * + */ + +#include <string> +#include <sockios/netinfo.h> + +#ifdef STLPORT +_STLP_BEGIN_NAMESPACE +#else +namespace std { +#endif + +::in_addr findhost( const char *hostname ) throw( std::domain_error ) +{ + in_addr inet; + int _errno; + +#ifndef __FIT_GETHOSTBYADDR + hostent _host; +# ifndef __hpux + char tmpbuf[1024]; +# else // __hpux + hostent_data tmpbuf; +# endif // __hpux +# ifdef __linux + hostent *host = 0; + gethostbyname_r( hostname, &_host, tmpbuf, 1024, &host, &_errno ); +# elif defined(__hpux) + _errno = gethostbyname_r( hostname, &_host, &tmpbuf ); + hostent *host = &_host; +# elif defined(__sun) + hostent *host = gethostbyname_r( hostname, &_host, tmpbuf, 1024, &_errno ); +# else // !__linux !__hpux !__sun +# error "Check port of gethostbyname_r" +# endif // __linux __hpux __sun + if ( host != 0 ) { + memcpy( (char *)&inet, (char *)host->h_addr, host->h_length ); + } +#else // __FIT_GETHOSTBYADDR + hostent *host = gethostbyname( hostname ); + if ( host != 0 ) { + memcpy( (char *)&inet, (char *)host->h_addr, host->h_length ); + } +# ifdef WIN32 + else { + _errno = WSAGetLastError(); + + // specific to Wins only: + // cool M$ can't resolve IP address in gethostbyname, try once more + // via inet_addr() and gethostbyaddr() + // Returned _errno depend upon WinSock version, and applied patches, + // with some of it even gethostbyname may be succeed. + if ( _errno == WSAHOST_NOT_FOUND || _errno == WSATRY_AGAIN ) { + unsigned long ipaddr = ::inet_addr( hostname ); + if ( ipaddr != INADDR_NONE ) { + host = gethostbyaddr( (const char *)&ipaddr, sizeof(ipaddr), AF_INET ); + if ( host != 0 ) { // Oh, that's was IP indeed... + memcpy( (char *)&inet, (char *)host->h_addr, host->h_length ); + WSASetLastError( 0 ); // clear error + _errno = 0; + } else { + _errno = WSAGetLastError(); + } + } + } + } +# endif // WIN32 +#endif // __FIT_GETHOSTBYADDR + if ( host == 0 ) { + throw std::domain_error( "host not found" ); + } + + return inet; +} + +std::string hostname( unsigned long inet_addr ) +{ + std::string _hostname; + +#ifdef __FIT_GETHOSTBYADDR + hostent *he; +#else + hostent he; +#ifndef __hpux + char tmp_buff[1024]; +#else + hostent_data tmp_buff; +#endif +# ifdef __linux + hostent *phe = 0; +# endif +#endif + int err = 0; + in_addr in; + in.s_addr = inet_addr; +#ifdef __FIT_GETHOSTBYADDR + // For Win 'he' is thread private data, so that's safe + // It's MT-safe also for HP-UX 11.00 + he = gethostbyaddr( (char *)&in.s_addr, sizeof(in_addr), AF_INET ); + if ( he != 0 ) { + _hostname = he->h_name; + } else { + _hostname = "unknown"; + } +#else // __FIT_GETHOSTBYADDR + if ( +# ifdef __sun + gethostbyaddr_r( (char *)&in.s_addr, sizeof(in_addr), AF_INET, + &he, tmp_buff, 1024, &err ) != 0 +# elif defined(__linux) + gethostbyaddr_r( (char *)&in.s_addr, sizeof(in_addr), AF_INET, + &he, tmp_buff, 1024, &phe, &err ) == 0 +# elif defined(__hpux) // reentrant variant for HP-UX before 11.00 + gethostbyaddr_r( (char *)&in.s_addr, sizeof(in_addr), AF_INET, + &he, &tmp_buff ) == 0 +# else +# error "Check port of gethostbyaddr_r" +# endif + ) + { + _hostname = he.h_name; + } else { + _hostname = "unknown"; + } +#endif // __FIT_GETHOSTBYADDR + + _hostname += " ["; + _hostname += inet_ntoa( in ); + _hostname += "]"; + + return _hostname; +} + +std::string hostname() +{ + std::string _hostname; + char tmp_buff[1024]; + + if ( gethostname( tmp_buff, 1024 ) == 0 ) { + _hostname = tmp_buff; + } else { + _hostname = "unknown"; + } + // getdomainname may be called here, but POSIX not specify such call + + return _hostname; +} + +int service( const char *name, const char *proto ) throw( std::domain_error ) +{ +#ifdef _WIN32 + typedef u_short uint16_t; +#endif +#ifndef __FIT_GETHOSTBYADDR + char tmp_buf[1024]; + struct servent se; +# ifdef __linux + struct servent *sep = 0; + if ( getservbyname_r( name, proto, &se, tmp_buf, 1024, &sep ) != 0 ) { + throw std::domain_error( "service not found" ); + } + return ntohs( uint16_t(se.s_port) ); +# endif +# ifdef __sun + if ( getservbyname_r( name, proto, &se, tmp_buf, 1024 ) == 0 ) { + throw std::domain_error( "service not found" ); + } + return ntohs( uint16_t(se.s_port) ); +# endif +#else // __FIT_GETHOSTBYADDR + struct servent *s = ::getservbyname( name, proto ); + if ( s == 0 ) { + throw std::domain_error( "service not found" ); + } + return ntohs( uint16_t(s->s_port) ); +#endif +} + +std::string service( int port, const char *proto ) throw( std::domain_error ) +{ +#ifdef _WIN32 + typedef u_short uint16_t; +#endif + std::string _servname; + + port = htons( uint16_t(port) ); + +#ifndef __FIT_GETHOSTBYADDR + char tmp_buf[1024]; + struct servent se; +# ifdef __linux + struct servent *sep = 0; + if ( getservbyport_r( port, proto, &se, tmp_buf, 1024, &sep ) != 0 ) { + throw std::domain_error( "service not found" ); + } + _servname.assign( se.s_name ); + return _servname; +# endif +# ifdef __sun + if ( getservbyport_r( port, proto, &se, tmp_buf, 1024 ) == 0 ) { + throw std::domain_error( "service not found" ); + } + _servname.assign( se.s_name ); + return _servname; +# endif +#else // __FIT_GETHOSTBYADDR + struct servent *s = ::getservbyport( port, proto ); + if ( s == 0 ) { + throw std::domain_error( "service not found" ); + } + _servname.assign( s->s_name ); + return _servname; +#endif +} + +#ifdef STLPORT +_STLP_END_NAMESPACE +#else +} // namespace std +#endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-02-28 11:15:22
|
Revision: 1825 http://complement.svn.sourceforge.net/complement/?rev=1825&view=rev Author: complement Date: 2008-02-28 03:15:13 -0800 (Thu, 28 Feb 2008) Log Message: ----------- include <typeinfo> Modified Paths: -------------- trunk/complement/explore/lib/mt/ut/mt_test_wg21.cc Modified: trunk/complement/explore/lib/mt/ut/mt_test_wg21.cc =================================================================== --- trunk/complement/explore/lib/mt/ut/mt_test_wg21.cc 2008-02-27 17:55:40 UTC (rev 1824) +++ trunk/complement/explore/lib/mt/ut/mt_test_wg21.cc 2008-02-28 11:15:13 UTC (rev 1825) @@ -15,6 +15,7 @@ #include <mt/mutex> #include <mt/condition_variable> #include <misc/type_traits.h> +#include <typeinfo> #include <iostream> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-02-27 17:55:44
|
Revision: 1824 http://complement.svn.sourceforge.net/complement/?rev=1824&view=rev Author: complement Date: 2008-02-27 09:55:40 -0800 (Wed, 27 Feb 2008) Log Message: ----------- instantiation experiments Modified Paths: -------------- trunk/complement/explore/inquiry/shades/sz/test.cc Modified: trunk/complement/explore/inquiry/shades/sz/test.cc =================================================================== --- trunk/complement/explore/inquiry/shades/sz/test.cc 2008-02-27 17:52:54 UTC (rev 1823) +++ trunk/complement/explore/inquiry/shades/sz/test.cc 2008-02-27 17:55:40 UTC (rev 1824) @@ -1,4 +1,5 @@ #include <iostream> +#include <typeinfo> // #include <string> char *arr[][2] = { @@ -7,12 +8,197 @@ { "2", "2.2" } }; +struct __select_types +{ + typedef char __t1; + struct __t2 + { + char __two[2]; + }; +}; + +template <class _Tp> +struct __instance : + public __select_types +{ + private: + template <class _Up> + static __t1 __test(_Up(*)[1]); + + template <class> + static __t2 __test(...); + + public: +#ifdef __FIT_NO_INLINE_TEMPLATE_STATIC_INITIALISATION + static const bool __value; +#else + static const bool __value = sizeof(__test<_Tp>(0)) == 1; +#endif + +}; + +#ifdef __FIT_NO_INLINE_TEMPLATE_STATIC_INITIALISATION +template <class _Tp> +const bool __instance<_Tp>::__value = sizeof(__instance<_Tp>::__test<_Tp>(0)) == 1; +#endif + +template <class T> +struct __uoc_aux : // union or class + public __select_types +{ + private: + template <class _Up> + static __t1 __test( int _Up::* ); + + template <class> + static __t2 __test(...); + + public: +#ifdef __FIT_NO_INLINE_TEMPLATE_STATIC_INITIALISATION + static const bool __value; +#else + static const bool __value = sizeof(__test<T>(0)) == 1; +#endif +}; + +#ifdef __FIT_NO_INLINE_TEMPLATE_STATIC_INITIALISATION +template <class T> +const bool __uoc_aux<T>::__value = sizeof(__uoc_aux<T>::__test<T>(0)) == 1; +#endif + +template <class T> +struct __xuoc_aux : // union or class + public __select_types +{ + private: + template <class _Up> + static __t1 __test( int (_Up::*)() ); + + template <class> + static __t2 __test(...); + + public: +#ifdef __FIT_NO_INLINE_TEMPLATE_STATIC_INITIALISATION + static const bool __value; +#else + static const bool __value = sizeof(__test<T>(0)) == 1; +#endif +}; + +#ifdef __FIT_NO_INLINE_TEMPLATE_STATIC_INITIALISATION +template <class T> +const bool __xuoc_aux<T>::__value = sizeof(__xuoc_aux<T>::__test<T>(0)) == 1; +#endif + +template <class T, bool B> +class __inheritance_aux +{}; + +template <class T> +class __inheritance_aux<T,false> : + public T +{ + public: + virtual ~__inheritance_aux() + { } +}; + + +template <class T, bool B> +struct __virtual_aux +{ + public: +#ifdef __FIT_NO_INLINE_TEMPLATE_STATIC_INITIALISATION + static const bool __value; +#else + static const bool __value = B ? false : (sizeof(__inheritance_aux<T,B>) == sizeof(T)); +#endif +}; + +#ifdef __FIT_NO_INLINE_TEMPLATE_STATIC_INITIALISATION +template <class T, bool B> +const bool __virtual_aux<T,B>::__value = B ? false : sizeof(__inheritance_aux<T,B>) == sizeof(T); +#endif + + +struct N +{ +}; + +struct M : + public N +{ +}; + +struct Q : + public N +{ + virtual ~Q() + { } +}; + +struct P +{ + virtual void x() + { } +}; + +struct R : + public P +{ + virtual ~R() + { } +}; + +union U +{ + int i; + double j; + + // int q( void (U::*)(void) ); +}; + +union UU +{ + int i; + double j; + + // int q( void (U::*)(void) ); +}; + +// struct DU : +// public U +// { +// }; + +template <class T> +struct DU +{ + // DU() : + // __value( typeid(T) == typeid(T) ) + // { } + + // static bool __value = typeid(T) == typeid(T); +}; + using namespace std; int main() { cerr << sizeof(arr) << " " << sizeof(arr[0]) << " " << sizeof(arr)/sizeof(arr[0]) << endl; + cerr << sizeof( N ) << " " << sizeof( M ) << " " << sizeof( Q ) << " " << sizeof(P) << " " + << sizeof( R ) << endl; + + cerr << __uoc_aux<N>::__value << " " << __xuoc_aux<N>::__value << endl; + + cerr << __virtual_aux<N,false>::__value << " " << __virtual_aux<int,true>::__value << " " + << __virtual_aux<Q,false>::__value << " " << __virtual_aux<R,false>::__value << endl; + + cerr << __xuoc_aux<U>::__value << endl; + + cerr << (typeid(U) == typeid(UU)) << endl; + #if 0 string s( "01234567Tabc" ); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-02-27 17:53:06
|
Revision: 1823 http://complement.svn.sourceforge.net/complement/?rev=1823&view=rev Author: complement Date: 2008-02-27 09:52:54 -0800 (Wed, 27 Feb 2008) Log Message: ----------- use xmt 2.0.0 interfaces [JTC1/SC22/WG21 working draft, threads]; libexam 0.7.0 Modified Paths: -------------- trunk/complement/explore/include/exam/logger.h trunk/complement/explore/include/exam/suite.h trunk/complement/explore/lib/exam/ChangeLog trunk/complement/explore/lib/exam/Makefile.inc trunk/complement/explore/lib/exam/logger.cc trunk/complement/explore/lib/exam/suite.cc Modified: trunk/complement/explore/include/exam/logger.h =================================================================== --- trunk/complement/explore/include/exam/logger.h 2008-02-27 16:44:54 UTC (rev 1822) +++ trunk/complement/explore/include/exam/logger.h 2008-02-27 17:52:54 UTC (rev 1823) @@ -1,7 +1,7 @@ -// -*- C++ -*- Time-stamp: <07/09/04 10:38:27 ptr> +// -*- C++ -*- Time-stamp: <08/02/24 17:09:51 ptr> /* - * Copyright (c) 2007 + * Copyright (c) 2007, 2008 * Petr Ovtchenkov * * Licensed under the Academic Free License Version 3.0 @@ -13,7 +13,7 @@ #include <string> #include <cstdio> #include <ostream> -#include <mt/time.h> +#include <mt/date_time> #include <list> namespace exam { @@ -129,7 +129,7 @@ virtual void tc( base_logger::tc_result, const std::string&, int ); private: - typedef std::list<xmt::timespec> time_container_t; + typedef std::list<std::tr2::nanoseconds> time_container_t; time_container_t tst; }; Modified: trunk/complement/explore/include/exam/suite.h =================================================================== --- trunk/complement/explore/include/exam/suite.h 2008-02-27 16:44:54 UTC (rev 1822) +++ trunk/complement/explore/include/exam/suite.h 2008-02-27 17:52:54 UTC (rev 1823) @@ -1,7 +1,7 @@ -// -*- C++ -*- Time-stamp: <07/09/04 11:08:48 ptr> +// -*- C++ -*- Time-stamp: <08/02/24 17:07:45 ptr> /* - * Copyright (c) 2007 + * Copyright (c) 2007, 2008 * Petr Ovtchenkov * * Licensed under the Academic Free License Version 3.0 @@ -21,7 +21,7 @@ #include <vector> #include <algorithm> -#include <mt/xmt.h> +#include <mt/mutex> #include <exam/logger.h> namespace exam { @@ -221,7 +221,7 @@ }; base_logger *local_logger; - xmt::mutex _lock_ll; + std::tr2::mutex _lock_ll; struct test_case_collect { @@ -249,10 +249,10 @@ static int _root_func( test_suite *, int = 0 ); static base_logger *logger; - static xmt::mutex _lock_gl; + static std::tr2::mutex _lock_gl; static std::stack<test_suite *> _stack; - static xmt::mutex _lock_stack; + static std::tr2::mutex _lock_stack; }; template <class TC> Modified: trunk/complement/explore/lib/exam/ChangeLog =================================================================== --- trunk/complement/explore/lib/exam/ChangeLog 2008-02-27 16:44:54 UTC (rev 1822) +++ trunk/complement/explore/lib/exam/ChangeLog 2008-02-27 17:52:54 UTC (rev 1823) @@ -1,3 +1,12 @@ +2008-02-27 Petr Ovtchenkov <pt...@is...> + + * suite.cc, logger.cc, suite.h, logger.h: use xmt 2.0.0 + interfaces [JTC1/SC22/WG21 working draft, threads]; + + * Makefile.inc: bump minor revision; + + * libexam: version 0.7.0. + 2007-12-17 Petr Ovtchenkov <pt...@is...> * logger.h, logger.cc, suite.h, suite.cc: dry run with Modified: trunk/complement/explore/lib/exam/Makefile.inc =================================================================== --- trunk/complement/explore/lib/exam/Makefile.inc 2008-02-27 16:44:54 UTC (rev 1822) +++ trunk/complement/explore/lib/exam/Makefile.inc 2008-02-27 17:52:54 UTC (rev 1823) @@ -1,7 +1,7 @@ -# -*- Makefile -*- Time-stamp: <07/09/04 11:12:48 ptr> +# -*- Makefile -*- Time-stamp: <08/02/24 17:18:31 ptr> LIBNAME = exam MAJOR = 0 -MINOR = 6 +MINOR = 7 PATCH = 0 SRC_CC = logger.cc suite.cc Modified: trunk/complement/explore/lib/exam/logger.cc =================================================================== --- trunk/complement/explore/lib/exam/logger.cc 2008-02-27 16:44:54 UTC (rev 1822) +++ trunk/complement/explore/lib/exam/logger.cc 2008-02-27 17:52:54 UTC (rev 1823) @@ -1,7 +1,7 @@ -// -*- C++ -*- Time-stamp: <07/09/04 10:47:22 ptr> +// -*- C++ -*- Time-stamp: <08/02/24 17:19:59 ptr> /* - * Copyright (c) 2007 + * Copyright (c) 2007, 2008 * Petr Ovtchenkov * * Licensed under the Academic Free License Version 3.0 @@ -13,6 +13,7 @@ namespace exam { using namespace std; +using namespace std::tr2; int base_logger::flags() const { @@ -139,12 +140,12 @@ void trivial_time_logger::tc_pre() { - tst.push_back( xmt::timespec( xmt::timespec::now ) ); + tst.push_back( get_system_time().nanoseconds_since_epoch() ); } void trivial_time_logger::tc_post() { - tst.back() = xmt::timespec( xmt::timespec::now ) - tst.back(); + tst.back() = get_system_time().nanoseconds_since_epoch() - tst.back(); } void trivial_time_logger::tc_break() @@ -159,11 +160,13 @@ time_container_t::const_iterator a = tst.begin(); if ( a != tst.end() ) { unsigned n = 1; - double sum(*a); + double sum(a->count()); + sum *= 1.0e-9; double sum_sq = sum * sum; ++a; for ( ; a != tst.end(); ++a ) { - double v(*a); + double v(a->count()); + v *= 1.0e-9; sum += v; sum_sq += v * v; // mean = ((n + 1) * mean + static_cast<double>(*a)) / (n + 2); @@ -191,11 +194,13 @@ time_container_t::const_iterator a = tst.begin(); if ( a != tst.end() ) { unsigned n = 1; - double sum(*a); + double sum(a->count()); + sum *= 1.0e-9; double sum_sq = sum * sum; ++a; for ( ; a != tst.end(); ++a ) { - double v(*a); + double v(a->count()); + v *= 1.0e-9; sum += v; sum_sq += v * v; // mean = ((n + 1) * mean + static_cast<double>(*a)) / (n + 2); Modified: trunk/complement/explore/lib/exam/suite.cc =================================================================== --- trunk/complement/explore/lib/exam/suite.cc 2008-02-27 16:44:54 UTC (rev 1822) +++ trunk/complement/explore/lib/exam/suite.cc 2008-02-27 17:52:54 UTC (rev 1823) @@ -1,7 +1,7 @@ -// -*- C++ -*- Time-stamp: <07/09/04 11:10:58 ptr> +// -*- C++ -*- Time-stamp: <08/02/24 19:11:47 ptr> /* - * Copyright (c) 2007 + * Copyright (c) 2007, 2008 * Petr Ovtchenkov * * Licensed under the Academic Free License Version 3.0 @@ -19,7 +19,7 @@ using namespace std; using namespace detail; -using namespace xmt; +using namespace std::tr2; int EXAM_IMPL(test_suite::_root_func) @@ -40,7 +40,7 @@ _test[0].tc = detail::make_test_case( detail::call( _root_func ) ); _test[0].state = 0; - scoped_lock lk( _lock_stack ); + lock_guard<mutex> lk( _lock_stack ); _stack.push( this ); } @@ -55,15 +55,16 @@ _test[0].tc = detail::make_test_case( detail::call( _root_func ) ); _test[0].state = 0; - scoped_lock lk( _lock_stack ); + lock_guard<mutex> lk( _lock_stack ); _stack.push( this ); } test_suite::~test_suite() { - scoped_lock lk( _lock_stack ); - _stack.pop(); - lk.unlock(); + { + lock_guard<mutex> lk( _lock_stack ); + _stack.pop(); + } for ( test_case_map_type::iterator i = _test.begin(); i != _test.end(); ++i ) { delete i->second.tc; @@ -164,21 +165,21 @@ int test_suite::flags() { - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); int tmp = local_logger->flags(); return tmp; } bool test_suite::is_trace() { - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); bool tmp = local_logger->is_trace(); return tmp; } int test_suite::flags( int f ) { - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); int tmp = local_logger->flags( f ); return tmp; } @@ -192,10 +193,10 @@ base_logger *test_suite::set_global_logger( base_logger *new_logger ) { - scoped_lock glk( _lock_gl ); + lock_guard<mutex> glk( _lock_gl ); base_logger *tmp = logger; logger = new_logger; - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); if ( tmp == local_logger ) { // if local_logger was identical to logger, switch it too local_logger = logger; } @@ -204,7 +205,7 @@ base_logger *test_suite::set_logger( base_logger *new_logger ) { - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); base_logger *tmp = local_logger; local_logger = new_logger; return tmp; @@ -215,13 +216,13 @@ if ( !cnd ) { _last_state = fail; } - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); local_logger->report( file, line, cnd, expr ); } void test_suite::report_async( const char *file, int line, bool cnd, const char *expr ) { - scoped_lock lk( _lock_stack ); + lock_guard<mutex> lk( _lock_stack ); if ( _stack.empty() ) { throw runtime_error( "stack of test suites empty" ); @@ -259,25 +260,25 @@ if ( res == 0 ) { if ( _last_state == 0 ) { ++_stat.passed; - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); local_logger->tc( base_logger::pass, _test[v].name ); } else { _test[v].state = fail; ++_stat.failed; - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); local_logger->tc( base_logger::fail, _test[v].name ); _last_state = 0; } } else { _test[v].state = fail; ++_stat.failed; - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); local_logger->tc( base_logger::fail, _test[v].name ); _last_state = 0; } } else { ++_stat.skipped; - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); local_logger->tc( base_logger::skip, _test[v].name ); } } @@ -286,7 +287,7 @@ local_logger->tc_break(); _lock_ll.unlock(); ++_stat.skipped; - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); local_logger->tc( base_logger::skip, _test[v].name ); } catch ( init_exception& ) { @@ -298,7 +299,7 @@ catch ( ... ) { ++_stat.failed; _test[v].state = fail; - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); local_logger->tc_break(); local_logger->tc( base_logger::fail, _test[v].name ); } @@ -323,7 +324,7 @@ _lock_ll.unlock(); } ++_stat.skipped; - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); local_logger->tc( base_logger::dry, _test[v].name, indent ); } catch ( skip_exception& ) { @@ -331,7 +332,7 @@ local_logger->tc_break(); _lock_ll.unlock(); ++_stat.skipped; - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); local_logger->tc( base_logger::skip, _test[v].name, indent ); } catch ( init_exception& ) { @@ -344,7 +345,7 @@ catch ( ... ) { ++_stat.failed; _test[v].state = fail; - scoped_lock lk( _lock_ll ); + lock_guard<mutex> lk( _lock_ll ); local_logger->tc_break(); local_logger->tc( base_logger::fail, _test[v].name, indent ); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-02-27 16:44:58
|
Revision: 1822 http://complement.svn.sourceforge.net/complement/?rev=1822&view=rev Author: complement Date: 2008-02-27 08:44:54 -0800 (Wed, 27 Feb 2008) Log Message: ----------- merge -r1806:1821 https://complement.svn.sourceforge.net/svnroot/complement/branches/wg21-thread Modified Paths: -------------- trunk/complement/explore/include/mt/system_error trunk/complement/explore/lib/mt/ChangeLog trunk/complement/explore/lib/mt/Makefile.inc trunk/complement/explore/lib/mt/system_error.cc trunk/complement/explore/lib/mt/ut/Makefile.inc trunk/complement/explore/lib/mt/ut/mt_test_suite.cc Added Paths: ----------- trunk/complement/explore/include/mt/condition_variable trunk/complement/explore/include/mt/date_time trunk/complement/explore/include/mt/mutex trunk/complement/explore/include/mt/thread trunk/complement/explore/lib/mt/date_time.cc trunk/complement/explore/lib/mt/thread.cc trunk/complement/explore/lib/mt/ut/mt_test_wg21.cc trunk/complement/explore/lib/mt/ut/mt_test_wg21.h Copied: trunk/complement/explore/include/mt/condition_variable (from rev 1821, branches/wg21-thread/include/mt/condition_variable) =================================================================== --- trunk/complement/explore/include/mt/condition_variable (rev 0) +++ trunk/complement/explore/include/mt/condition_variable 2008-02-27 16:44:54 UTC (rev 1822) @@ -0,0 +1,773 @@ +// -*- C++ -*- Time-stamp: <08/02/25 13:09:15 ptr> + +/* + * Copyright (c) 1997-1999, 2002-2008 + * Petr Ovtchenkov + * + * Portion Copyright (c) 1999-2001 + * Parallel Graphics Ltd. + * + * Licensed under the Academic Free License version 3.0 + * + * Derived from original <mt/xmt.h> of 'complement' project + * [http://complement.sourceforge.net] + * to make it close to JTC1/SC22/WG21 working draft + * [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2497.html] + */ + +#ifndef __MT_CONDITION_VARIABLE +#define __MT_CONDITION_VARIABLE + +#ifndef __config_feature_h +#include <config/feature.h> +#endif + +#include <mt/date_time> +#include <mt/mutex> + +namespace std { + +namespace tr2 { + +template <bool SCOPE> +class __condition_variable +{ + public: + __condition_variable() + { +#ifdef __FIT_WIN32THREADS + _cond = CreateEvent( 0, TRUE, TRUE, 0 ); +#endif +#ifdef __FIT_PTHREADS + if ( SCOPE ) { + pthread_condattr_t attr; + pthread_condattr_init( &attr ); + pthread_condattr_setpshared( &attr, PTHREAD_PROCESS_SHARED ); + pthread_cond_init( &_cond, &attr ); + pthread_condattr_destroy( &attr ); + } else { + pthread_cond_init( &_cond, 0 ); + } +#endif + } + + ~__condition_variable() + { +#ifdef __FIT_WIN32THREADS + CloseHandle( _cond ); +#endif +#ifdef __FIT_PTHREADS + pthread_cond_destroy( &_cond ); +#endif + } + +#ifdef __FIT_PTHREADS + typedef pthread_cond_t* native_handle_type; +#endif +#ifdef __FIT_WIN32THREADS + typedef HANDLE native_handle_type; +#endif + + void notify_one() + { +#ifdef __FIT_WIN32THREADS + SetEvent( _cond ); +#endif +#ifdef __FIT_PTHREADS + pthread_cond_signal( &_cond ); +#endif + } + + void notify_all() + { +#ifdef __FIT_PTHREADS + pthread_cond_broadcast( &_cond ); +#endif + } + + void wait( unique_lock<__mutex<false,SCOPE> >& lock ) + { +#ifdef __FIT_WIN32THREADS + ResetEvent( _cond ); + lock.unlock(); + if ( WaitForSingleObject( _cond, -1 ) == WAIT_FAILED ) { + lock.lock(); + // throw system_error + } + lock.lock(); +#endif +#ifdef __FIT_PTHREADS + int ret = pthread_cond_wait( &_cond, &lock.m->_M_lock ); + if ( ret ) { + lock.lock(); + // throw system_error + } +#endif + } + + template <class Predicate> + void wait( unique_lock<__mutex<false,SCOPE> >& lock, Predicate pred ) + { + while ( !pred() ) { + wait( lock ); + } + } + + bool timed_wait( unique_lock<__mutex<false,SCOPE> >& lock, const system_time& abs_time ) + { +#ifdef __FIT_PTHREADS + ::timespec t; + t.tv_sec = abs_time.seconds_since_epoch(); + t.tv_nsec = static_cast<long>( abs_time.nanoseconds_since_epoch().count() % nanoseconds::ticks_per_second ); + int ret = pthread_cond_timedwait( &_cond, &lock.m->_M_lock, &t ); + if ( ret != 0 ) { + if ( ret == ETIMEDOUT ) { + return false; + } + // throw system_error + } +#endif + return true; + } + + template <class Duration> + bool timed_wait( unique_lock<__mutex<false,SCOPE> >& lock, const Duration& rel_time ) + { +#ifdef __FIT_PTHREADS + return timed_wait( lock, get_system_time() + rel_time ); +#endif + } + + template <class Predicate> + bool timed_wait( unique_lock<__mutex<false,SCOPE> >& lock, const system_time& abs_time, Predicate pred ) + { + while ( !pred() ) { + if ( !timed_wait( lock, abs_time ) ) { + return pred(); + } + } + return true; + } + + template <class Duration, class Predicate> + bool timed_wait( unique_lock<__mutex<false,SCOPE> >& lock, const Duration& rel_time, Predicate pred ) + { +#ifdef __FIT_PTHREADS + return timed_wait( lock, get_system_time() + rel_time, pred ); +#endif + } + + native_handle_type native_handle() + { +#ifdef __FIT_PTHREADS + return &_cond; +#endif +#ifdef __FIT_WIN32THREADS + return _cond; +#endif + } + + protected: +#ifdef __FIT_PTHREADS + pthread_cond_t _cond; +#endif +#ifdef __FIT_WIN32THREADS + HANDLE _cond; +#endif + + private: + __condition_variable( const __condition_variable& ) + { } +}; + +typedef __condition_variable<false> condition_variable; +typedef __condition_variable<true> condition_variable_ip; + +template <bool SCOPE> +class __condition_variable_any +{ + public: + __condition_variable_any() + { +#ifdef __FIT_WIN32THREADS + _cond = CreateEvent( 0, TRUE, TRUE, 0 ); +#endif +#ifdef __FIT_PTHREADS + if ( SCOPE ) { + pthread_condattr_t attr; + pthread_condattr_init( &attr ); + pthread_condattr_setpshared( &attr, PTHREAD_PROCESS_SHARED ); + pthread_cond_init( &_cond, &attr ); + pthread_condattr_destroy( &attr ); + } else { + pthread_cond_init( &_cond, 0 ); + } +#endif + } + + ~__condition_variable_any() + { +#ifdef __FIT_WIN32THREADS + CloseHandle( _cond ); +#endif +#ifdef __FIT_PTHREADS + pthread_cond_destroy( &_cond ); +#endif + } + +#ifdef __FIT_PTHREADS + typedef pthread_cond_t* native_handle_type; +#endif +#ifdef __FIT_WIN32THREADS + typedef HANDLE native_handle_type; +#endif + + void notify_one() + { +#ifdef __FIT_WIN32THREADS + SetEvent( _cond ); +#endif +#ifdef __FIT_PTHREADS + pthread_cond_signal( &_cond ); +#endif + } + + void notify_all() + { +#ifdef __FIT_PTHREADS + pthread_cond_broadcast( &_cond ); +#endif + } + + template <class Lock> + void wait( Lock& lock ) + { +#ifdef __FIT_WIN32THREADS + ResetEvent( _cond ); + lock.unlock(); + if ( WaitForSingleObject( _cond, -1 ) == WAIT_FAILED ) { + lock.lock(); + // throw system_error + } + lock.lock(); +#endif +#ifdef __FIT_PTHREADS + int ret = pthread_cond_wait( &_cond, lock.native_handle() ); + if ( ret ) { + lock.lock(); + // throw system_error + } +#endif + } + + template <class Lock, class Predicate> + void wait( Lock& lock, Predicate pred ) + { + while ( !pred() ) { + wait( lock ); + } + } + + template <class Lock> + bool timed_wait( Lock& lock, const system_time& abs_time ) + { +#ifdef __FIT_PTHREADS + ::timespec t; + t.tv_sec = abs_time.seconds_since_epoch(); + t.tv_nsec = static_cast<long>( abs_time.nanoseconds_since_epoch().count() % nanoseconds::ticks_per_second ); + int ret = pthread_cond_timedwait( &_cond, lock.native_handle(), &t ); + if ( ret != 0 ) { + if ( ret == ETIMEDOUT ) { + return false; + } + // throw system_error + } +#endif +#ifdef __FIT_WIN32THREADS + static const std::tr2::nanoseconds::tick_type _th = std::tr2::nanoseconds::ticks_per_second / std::tr2::milliseconds::ticks_per_second; + ResetEvent( _cond ); + lock.unlock(); + int ret = WaitForSingleObject( _cond, (abs_time - get_system_time()).count() / _th ); + lock.lock(); + if ( ret == WAIT_FAILED ) { + // throw system_error + } + if ( ret == WAIT_TIMEOUT ) { + SetEvent( _cond ); + return _val; + } +#endif + + return true; + } + + template <class Lock, class Duration> + bool timed_wait( Lock& lock, const Duration& rel_time ) + { +#ifdef __FIT_PTHREADS + return timed_wait( lock, get_system_time() + rel_time ); +#endif +#ifdef __FIT_WIN32THREADS + static const std::tr2::nanoseconds::tick_type _th = std::tr2::nanoseconds::ticks_per_second / Duration::ticks_per_second; + + ResetEvent( _cond ); + lock.unlock(); + int ret = WaitForSingleObject( _cond, rel_time.count() / _th ); + lock.lock(); + if ( ret == WAIT_FAILED ) { + // throw system_error + } + if ( ret == WAIT_TIMEOUT ) { + SetEvent( _cond ); + return _val; + } + + return true; +#endif + } + + template <class Lock, class Predicate> + bool timed_wait( Lock& lock, const system_time& abs_time, Predicate pred ) + { + while ( !pred() ) { + if ( !timed_wait( lock, abs_time ) ) { + return pred(); + } + } + return true; + } + + template <class Lock, class Duration, class Predicate> + bool timed_wait( Lock& lock, const Duration& rel_time, Predicate pred ) + { +#ifdef __FIT_PTHREADS + return timed_wait( lock, get_system_time() + rel_time, pred ); +#endif + } + + native_handle_type native_handle() + { +#ifdef __FIT_PTHREADS + return &_cond; +#endif +#ifdef __FIT_WIN32THREADS + return _cond; +#endif + } + + protected: +#ifdef __FIT_PTHREADS + pthread_cond_t _cond; +#endif +#ifdef __FIT_WIN32THREADS + HANDLE _cond; +#endif + + private: + __condition_variable_any( const __condition_variable_any& ) + { } +}; + +typedef __condition_variable_any<false> condition_variable_any; +typedef __condition_variable_any<true> condition_variable_any_ip; + +template <bool SCOPE> +class __condition_event +{ + public: + __condition_event() : + _val( false ) + { +#ifdef __FIT_WIN32THREADS + _cond = CreateEvent( 0, TRUE, TRUE, 0 ); +#endif +#ifdef __FIT_PTHREADS + if ( SCOPE ) { + pthread_condattr_t attr; + pthread_condattr_init( &attr ); + pthread_condattr_setpshared( &attr, PTHREAD_PROCESS_SHARED ); + pthread_cond_init( &_cond, &attr ); + pthread_condattr_destroy( &attr ); + } else { + pthread_cond_init( &_cond, 0 ); + } +#endif + } + + ~__condition_event() + { +#ifdef __FIT_WIN32THREADS + CloseHandle( _cond ); +#endif +#ifdef __FIT_PTHREADS + pthread_cond_destroy( &_cond ); +#endif + } + + void notify_one() + { + { + unique_lock<__mutex<false,SCOPE> > lk( _lock ); + + if ( _val ) { + return; + } + + _val = true; + } + +#ifdef __FIT_WIN32THREADS + SetEvent( _cond ); +#endif +#ifdef __FIT_PTHREADS + if ( pthread_cond_signal( &_cond ) ) { + // throw system_error + } +#endif + } + + void notify_all() + { + { + unique_lock<__mutex<false,SCOPE> > lk( _lock ); + + if ( _val ) { + return; + } + + _val = true; + } + +#ifdef __FIT_WIN32THREADS + if ( SetEvent( _cond ) == FALSE ) { + // throw system_error + } +#endif +#ifdef __FIT_PTHREADS + if ( pthread_cond_broadcast( &_cond ) ) { + // throw system_error + } +#endif + } + + void reset() + { + unique_lock<__mutex<false,SCOPE> > lk( _lock ); + _val = false; + } + + void wait() + { + unique_lock<__mutex<false,SCOPE> > lk( _lock ); + +#ifdef __FIT_WIN32THREADS + ResetEvent( _cond ); + lk.unlock(); + if ( WaitForSingleObject( _cond, -1 ) == WAIT_FAILED ) { + lk.lock(); + // throw system_error + } + lk.lock(); +#endif +#ifdef __FIT_PTHREADS + int ret; + while ( !_val ) { + ret = pthread_cond_wait( &_cond, &_lock._M_lock ); + if ( ret ) { + // throw system_error + } + } +#endif + } + + bool timed_wait(const system_time& abs_time ) + { + unique_lock<__mutex<false,SCOPE> > lk( _lock ); + +#ifdef __FIT_PTHREADS + ::timespec t; + t.tv_sec = abs_time.seconds_since_epoch(); + t.tv_nsec = static_cast<long>( abs_time.nanoseconds_since_epoch().count() % nanoseconds::ticks_per_second ); + while ( !_val ) { + int ret = pthread_cond_timedwait( &_cond, _lock.native_handle(), &t ); + if ( ret != 0 ) { + if ( ret == ETIMEDOUT ) { + return _val; + } + // throw system_error + } + } +#endif + +#ifdef __FIT_WIN32THREADS + static const std::tr2::nanoseconds::tick_type _th = std::tr2::nanoseconds::ticks_per_second / std::tr2::milliseconds::ticks_per_second; + ResetEvent( _cond ); + lk.unlock(); + int ret = WaitForSingleObject( _cond, (abs_time - get_system_time()).count() / _th ); + lk.lock(); + if ( ret == WAIT_FAILED ) { + // throw system_error + } + if ( ret == WAIT_TIMEOUT ) { + SetEvent( _cond ); + return _val; + } +#endif + + return true; + } + + template <class Duration> + bool timed_wait( const Duration& rel_time ) + { +#ifdef __FIT_PTHREADS + return timed_wait( get_system_time() + rel_time ); +#endif +#ifdef __FIT_WIN32THREADS + static const std::tr2::nanoseconds::tick_type _th = std::tr2::nanoseconds::ticks_per_second / Duration::ticks_per_second; + + unique_lock<__mutex<false,SCOPE> > lk( _lock ); + + ResetEvent( _cond ); + lk.unlock(); + int ret = WaitForSingleObject( _cond, rel_time.count() / _th ); + lk.lock(); + if ( ret == WAIT_FAILED ) { + // throw system_error + } + if ( ret == WAIT_TIMEOUT ) { + SetEvent( _cond ); + return _val; + } + + return true; +#endif + } + + protected: +#ifdef __FIT_WIN32THREADS + HANDLE _cond; +#endif +#ifdef __FIT_PTHREADS + pthread_cond_t _cond; +#endif + __mutex<false,SCOPE> _lock; + bool _val; + + private: + __condition_event( const __condition_event& ) + { } +}; + +typedef __condition_event<false> condition_event; +typedef __condition_event<true> condition_event_ip; + +template <bool SCOPE> +class __semaphore +{ + public: + __semaphore( int cnt = 1 ) + { +#ifdef __FIT_WIN32THREADS + _sem = CreateSemaphore( NULL, cnt, INT_MAX, 0 ); // check! + _cnt = cnt; +#endif +#ifdef __FIT_PTHREADS + sem_init( &_sem, SCOPE ? 1 : 0, cnt ); +#endif + } + + ~__semaphore() + { +#ifdef __FIT_WIN32THREADS + CloseHandle( _sem ); +#endif +#ifdef __FIT__PTHREADS + sem_destroy( &_sem ); +#endif + } + + void wait() + { +#ifdef __FIT_WIN32THREADS + --_cnt; + if ( WaitForSingleObject( _sem, -1 ) == WAIT_FAILED ) { + ++_cnt; + // throw system_error + } +#endif +#ifdef __FIT_PTHREADS + int ret = sem_wait( &_sem ); + if ( ret != 0 ) { + // throw system_error + } +#endif + } + + bool try_wait() + { +#ifdef __FIT_WIN32THREADS + return _cnt > 0 ? (--_cnt, this->wait()) : -1; +#endif +#ifdef __FIT_PTHREADS + int ret = sem_trywait( &_sem ); + if ( ret != 0 ) { + if ( ret == EBUSY ) { + return false; + } + // throw system_error + } + return true; +#endif + } + + bool timed_wait(const system_time& abs_time ) + { +#ifdef __FIT_PTHREADS + ::timespec t; + t.tv_sec = abs_time.seconds_since_epoch(); + t.tv_nsec = static_cast<long>( abs_time.nanoseconds_since_epoch().count() % nanoseconds::ticks_per_second ); +# if !(defined(__FreeBSD__) || defined(__OpenBSD__)) + int ret = sem_timedwait( &_sem, &t ); + if ( ret != 0 ) { + if ( ret == ETIMEDOUT ) { + return false; + } + // throw system_error + } +# endif +#endif +#ifdef __FIT_WIN32THREADS + static const std::tr2::nanoseconds::tick_type _th = std::tr2::nanoseconds::ticks_per_second / std::tr2::milliseconds::ticks_per_second; + int ret = WaitForSingleObject( _sem, (abs_time - get_system_time()).count() / _th ); + if ( ret == WAIT_FAILED ) { + // throw system_error + } + if ( ret == WAIT_TIMEOUT ) { + return false; + } +#endif + return true; + } + + template <class Duration> + bool timed_wait( const Duration& rel_time ) + { +#ifdef __FIT_PTHREADS + return timed_wait( get_system_time() + rel_time ); +#endif +#ifdef __FIT_WIN32THREADS + static const std::tr2::nanoseconds::tick_type _th = std::tr2::nanoseconds::ticks_per_second / Duration::ticks_per_second; + + int ret = WaitForSingleObject( _sem, rel_time.count() / _th ); + + if ( ret == WAIT_OBJECT_0 ) { + return true; + } + + if ( ret == WAIT_FAILED ) { + // throw system_error + } + if ( ret == WAIT_TIMEOUT ) { + return false; + } + + return true; +#endif + } + + + void notify_one() + { +#ifdef __FIT_WIN32THREADS + int ret = ReleaseSemaphore( _sem, 1, &_cnt ) != 0 ? (++_cnt, 0) : -1; + if ( ret != 0 ) { + // throw system_error + } +#endif +#ifdef __FIT_PTHREADS + int ret = sem_post( &_sem ); + if ( ret != 0 ) { + // throw system_error + } +#endif + } + + int value() + { +#ifdef __FIT_WIN32THREADS + return static_cast<int>(_cnt); +#endif +#ifdef __FIT_PTHREADS + int v; + int e = sem_getvalue( &_sem, &v ); + if ( e != 0 ) { + // throw system_error + } + + return v; +#endif + } + + protected: +#ifdef __FIT_WIN32THREADS + HANDLE _sem; + long _cnt; +#endif +#ifdef __FIT_PTHREADS + sem_t _sem; +#endif + private: + __semaphore( const __semaphore& ) + { } +}; + +typedef __semaphore<false> semaphore; +typedef __semaphore<true> semaphore_ip; + +template <bool SCOPE> +class __barrier +{ + public: + __barrier( unsigned cnt = 2 ) + { +#ifdef _PTHREADS + pthread_barrierattr_t attr; + pthread_barrierattr_init( &attr ); + pthread_barrierattr_setpshared( &attr, SCOPE ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE ); + pthread_barrier_init( &_barr, &attr, cnt ); + pthread_barrierattr_destroy( &attr ); +#endif + } + + ~__barrier() + { +#ifdef __FIT_PTHREADS + pthread_barrier_destroy( &_barr ); +#endif + } + + void wait() + { +#ifdef __FIT_PTHREADS + int ret = pthread_barrier_wait( &_barr ); + if ( ret != 0 ) { + // throw system_error + } +#endif + } + + private: +#ifdef __FIT_PTHREADS + pthread_barrier_t _barr; +#endif +}; + +typedef __barrier<false> barrier; +typedef __barrier<false> barrier_ip; + +} // namespace tr2 + +} // namespace std + +#endif // __MT_CONDITION_VARIABLE Copied: trunk/complement/explore/include/mt/date_time (from rev 1821, branches/wg21-thread/include/mt/date_time) =================================================================== --- trunk/complement/explore/include/mt/date_time (rev 0) +++ trunk/complement/explore/include/mt/date_time 2008-02-27 16:44:54 UTC (rev 1822) @@ -0,0 +1,1116 @@ +// -*- C++ -*- Time-stamp: <08/02/25 13:08:13 ptr> + +/* + * Copyright (c) 2002, 2006-2008 + * Petr Ovtchenkov + * + * Licensed under the Academic Free License version 3.0 + * + * Derived from original <mt/time.h> of 'complement' project + * [http://complement.sourceforge.net] + * to make it close to JTC1/SC22/WG21 working draft + * [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2497.html] + */ + +#ifndef __MT_DATE_TIME +#define __MT_DATE_TIME + +#ifndef __config_feature_h +#include <config/feature.h> +#endif + +#include <string> +#include <misc/type_traits.h> +#include <functional> + +namespace std { + +namespace tr2 { + +class system_time; +class nanoseconds; +class microseconds; +class milliseconds; +class seconds; +class minutes; +class hours; + +namespace detail { + +typedef long long signed_tick_type; // int64_t +typedef unsigned long long unsigned_tick_type; // uint64_t + +template <class _Tp1, class _Tp2> +struct __is_more_precise : + public std::tr1::false_type +{ + typedef _Tp2 finest_type; +}; + +template <class _Tp> +struct __is_more_precise<std::tr2::nanoseconds,_Tp> : + public std::tr1::true_type +{ + typedef std::tr2::nanoseconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::microseconds,milliseconds> : + public std::tr1::true_type +{ + typedef std::tr2::microseconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::microseconds,seconds> : + public std::tr1::true_type +{ + typedef std::tr2::microseconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::microseconds,minutes> : + public std::tr1::true_type +{ + typedef std::tr2::microseconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::microseconds,hours> : + public std::tr1::true_type +{ + typedef std::tr2::microseconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::milliseconds,seconds> : + public std::tr1::true_type +{ + typedef std::tr2::milliseconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::milliseconds,minutes> : + public std::tr1::true_type +{ + typedef std::tr2::milliseconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::milliseconds,hours> : + public std::tr1::true_type +{ + typedef std::tr2::milliseconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::seconds,minutes> : + public std::tr1::true_type +{ + typedef std::tr2::seconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::seconds,hours> : + public std::tr1::true_type +{ + typedef std::tr2::seconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::minutes,hours> : + public std::tr1::true_type +{ + typedef std::tr2::minutes finest_type; +}; + +template <class LhsDuration, class RhsDuration, class Op, bool Pre> +struct __op_aux +{ + bool operator()( const LhsDuration& lhs, const RhsDuration& rhs ) const + { return Op()( static_cast<RhsDuration>(lhs).count(), rhs.count()); } +}; + +template <class LhsDuration, class RhsDuration, class Op> +struct __op_aux<LhsDuration,RhsDuration,Op,true> +{ + bool operator()( const LhsDuration& lhs, const RhsDuration& rhs ) const + { return Op()(lhs.count(), static_cast<LhsDuration>(rhs).count() ); } +}; + +template <class LhsDuration, class RhsDuration, class Op, bool Pre> +struct __op_aux2 +{ + signed_tick_type operator()( const LhsDuration& lhs, const RhsDuration& rhs ) const + { return Op()( static_cast<RhsDuration>(lhs).count(), rhs.count()); } +}; + +template <class LhsDuration, class RhsDuration, class Op> +struct __op_aux2<LhsDuration,RhsDuration,Op,true> +{ + signed_tick_type operator()( const LhsDuration& lhs, const RhsDuration& rhs ) const + { return Op()(lhs.count(), static_cast<LhsDuration>(rhs).count() ); } +}; + +struct add : + public std::binary_function<signed_tick_type,signed_tick_type,signed_tick_type> +{ + signed_tick_type operator()(signed_tick_type __x, signed_tick_type __y) const + { return __x + __y; } +}; + +struct sub : + public std::binary_function<signed_tick_type,signed_tick_type,signed_tick_type> +{ + signed_tick_type operator()(signed_tick_type __x, signed_tick_type __y) const + { return __x - __y; } +}; + +} // namespace detail + +class nanoseconds +{ + public: + typedef std::tr2::detail::signed_tick_type tick_type; + + static const tick_type ticks_per_second; + static const tick_type seconds_per_tick; + static const bool is_subsecond; + + nanoseconds( long long ns = 0LL ) : + tv( ns ) + { } + + tick_type count() const + { return tv; } + + template <typename Duration> + nanoseconds& operator -=( const Duration& d ) + { + static const tick_type factor = Duration::is_subsecond ? nanoseconds::ticks_per_second / Duration::ticks_per_second : nanoseconds::ticks_per_second * Duration::seconds_per_tick; + + tv -= d.tv * factor; + return *this; + } + + template <typename Duration> + nanoseconds& operator +=( const Duration& d ) + { + static const tick_type factor = Duration::is_subsecond ? nanoseconds::ticks_per_second / Duration::ticks_per_second : nanoseconds::ticks_per_second * Duration::seconds_per_tick; + + tv += d.tv * factor; + return *this; + } + + nanoseconds& operator *=( long v ) + { + tv *= v; + return *this; + } + + nanoseconds& operator /=( long v ) + { + tv /= v; + return *this; + } + + nanoseconds operator -() const + { return nanoseconds( -tv ); } + + bool operator ==( const nanoseconds& r ) const + { return tv == r.tv; } + + template <class Duration> + bool operator ==( const Duration& r ) const + { return tv == static_cast<nanoseconds>(r).count(); } + + bool operator !=( const nanoseconds& r ) const + { return tv != r.tv; } + + template <class Duration> + bool operator !=( const Duration& r ) const + { return tv != static_cast<nanoseconds>(r).count(); } + + bool operator <( const nanoseconds& r ) const + { return tv < r.tv; } + + template <class Duration> + bool operator <( const Duration& r ) const + { return tv < static_cast<nanoseconds>(r).count(); } + + bool operator <=( const nanoseconds& r ) const + { return tv <= r.tv; } + + template <class Duration> + bool operator <=( const Duration& r ) const + { return tv <= static_cast<nanoseconds>(r).count(); } + + bool operator >( const nanoseconds& r ) const + { return tv > r.tv; } + + template <class Duration> + bool operator >( const Duration& r ) const + { return tv > static_cast<nanoseconds>(r).count(); } + + bool operator >=( const nanoseconds& r ) const + { return tv >= r.tv; } + + template <class Duration> + bool operator >=( const Duration& r ) const + { return tv >= static_cast<nanoseconds>(r).count(); } + + nanoseconds operator +( const nanoseconds& r ) const + { return nanoseconds( tv + r.tv ); } + + system_time operator +( const system_time& r ) const; + + template <class Duration> + nanoseconds operator +(const Duration& r) const + { return nanoseconds( tv + static_cast<nanoseconds>(r).count() ); } + + nanoseconds operator -( const nanoseconds& r ) const + { return nanoseconds( tv - r.tv ); } + + template <class Duration> + nanoseconds operator -(const Duration& r) const + { return nanoseconds( tv - static_cast<nanoseconds>(r).count() ); } + + nanoseconds operator *( long r ) const + { return nanoseconds( tv * r ); } + + nanoseconds operator /( long r ) const + { return nanoseconds( tv / r ); } + + private: + tick_type tv; + + friend class microseconds; + friend class milliseconds; + friend class seconds; + friend class minutes; + friend class hours; +}; + +class microseconds +{ + public: + typedef std::tr2::detail::signed_tick_type tick_type; + + static const tick_type ticks_per_second; + static const tick_type seconds_per_tick; + static const bool is_subsecond; + + microseconds( long long us = 0LL ) : + tv( us ) + { } + + tick_type count() const + { return tv; } + + template <typename RhsDuration> + microseconds& operator -=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv -= d.tv * factor / 1000LL; + return *this; + } + + + template <typename RhsDuration> + microseconds& operator +=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv += d.tv * factor / 1000LL; + return *this; + } + + + microseconds& operator *=( long v ) + { + tv *= v; + return *this; + } + + microseconds& operator /=( long v ) + { + tv /= v; + return *this; + } + + microseconds operator -() const + { return microseconds( -tv ); } + + operator nanoseconds() const + { return nanoseconds(tv * 1000LL); } + + bool operator ==( const microseconds& r ) const + { return tv == r.tv; } + + template <class Duration> + bool operator ==( const Duration& r ) const + { return std::tr2::detail::__op_aux<microseconds,Duration,std::equal_to<tick_type>,std::tr2::detail::__is_more_precise<microseconds,Duration>::value>()( *this, r ); } + + bool operator !=( const microseconds& r ) const + { return tv != r.tv; } + + template <class Duration> + bool operator !=( const Duration& r ) const + { return std::tr2::detail::__op_aux<microseconds,Duration,std::not_equal_to<tick_type>,std::tr2::detail::__is_more_precise<microseconds,Duration>::value>()( *this, r ); } + + bool operator <( const microseconds& r ) const + { return tv < r.tv; } + + template <class Duration> + bool operator <( const Duration& r ) const + { return std::tr2::detail::__op_aux<microseconds,Duration,std::less<tick_type>,std::tr2::detail::__is_more_precise<microseconds,Duration>::value>()( *this, r ); } + + bool operator <=( const microseconds& r ) const + { return tv <= r.tv; } + + template <class Duration> + bool operator <=( const Duration& r ) const + { return std::tr2::detail::__op_aux<microseconds,Duration,std::less_equal<tick_type>,std::tr2::detail::__is_more_precise<microseconds,Duration>::value>()( *this, r ); } + + bool operator >( const microseconds& r ) const + { return tv > r.tv; } + + template <class Duration> + bool operator >( const Duration& r ) const + { return std::tr2::detail::__op_aux<microseconds,Duration,std::greater<tick_type>,std::tr2::detail::__is_more_precise<microseconds,Duration>::value>()( *this, r ); } + + bool operator >=( const microseconds& r ) const + { return tv >= r.tv; } + + template <class Duration> + bool operator >=( const Duration& r ) const + { return std::tr2::detail::__op_aux<microseconds,Duration,std::greater_equal<tick_type>,std::tr2::detail::__is_more_precise<microseconds,Duration>::value>()( *this, r ); } + + microseconds operator +( const microseconds& r ) const + { return microseconds( tv + r.tv ); } + + system_time operator +( const system_time& r ) const; + + template <class Duration> + typename std::tr2::detail::__is_more_precise<microseconds,Duration>::finest_type operator +(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<microseconds,Duration>::finest_type( + std::tr2::detail::__op_aux2<microseconds,Duration,std::tr2::detail::add,std::tr2::detail::__is_more_precise<microseconds,Duration>::value>()( *this, r ) ); + } + + microseconds operator -( const microseconds& r ) const + { return microseconds( tv - r.tv ); } + + template <class Duration> + typename std::tr2::detail::__is_more_precise<microseconds,Duration>::finest_type operator -(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<microseconds,Duration>::finest_type( + std::tr2::detail::__op_aux2<microseconds,Duration,std::tr2::detail::sub,std::tr2::detail::__is_more_precise<microseconds,Duration>::value>()( *this, r ) ); + } + + microseconds operator *( long r ) const + { return microseconds( tv * r ); } + + microseconds operator /( long r ) const + { return microseconds( tv / r ); } + + private: + tick_type tv; + + friend class nanoseconds; + friend class milliseconds; + friend class seconds; + friend class minutes; + friend class hours; +}; + +class milliseconds +{ + public: + typedef std::tr2::detail::signed_tick_type tick_type; + + static const tick_type ticks_per_second; + static const tick_type seconds_per_tick; + static const bool is_subsecond; + + milliseconds( long long ms = 0LL ) : + tv( ms ) + { } + + tick_type count() const + { return tv; } + + template <typename RhsDuration> + milliseconds& operator -=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv -= d.tv * factor / 1000000LL; + return *this; + } + + + template <typename RhsDuration> + milliseconds& operator +=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv += d.tv * factor / 1000000LL; + return *this; + } + + + milliseconds& operator *=( long v ) + { + tv *= v; + return *this; + } + + milliseconds& operator /=( long v ) + { + tv /= v; + return *this; + } + + milliseconds operator -() const + { return milliseconds( -tv ); } + + operator nanoseconds() const + { return nanoseconds(tv * 1000000LL); } + + operator microseconds() const + { return microseconds(tv * 1000LL); } + + bool operator ==( const milliseconds& r ) const + { return tv == r.tv; } + + template <class Duration> + bool operator ==( const Duration& r ) const + { return std::tr2::detail::__op_aux<milliseconds,Duration,std::equal_to<tick_type>,std::tr2::detail::__is_more_precise<milliseconds,Duration>::value>()( *this, r ); } + + bool operator !=( const milliseconds& r ) const + { return tv != r.tv; } + + template <class Duration> + bool operator !=( const Duration& r ) const + { return std::tr2::detail::__op_aux<milliseconds,Duration,std::not_equal_to<tick_type>,std::tr2::detail::__is_more_precise<milliseconds,Duration>::value>()( *this, r ); } + + bool operator <( const milliseconds& r ) const + { return tv < r.tv; } + + template <class Duration> + bool operator <( const Duration& r ) const + { return std::tr2::detail::__op_aux<milliseconds,Duration,std::less<tick_type>,std::tr2::detail::__is_more_precise<milliseconds,Duration>::value>()( *this, r ); } + + bool operator <=( const milliseconds& r ) const + { return tv <= r.tv; } + + template <class Duration> + bool operator <=( const Duration& r ) const + { return std::tr2::detail::__op_aux<milliseconds,Duration,std::less_equal<tick_type>,std::tr2::detail::__is_more_precise<milliseconds,Duration>::value>()( *this, r ); } + + bool operator >( const milliseconds& r ) const + { return tv > r.tv; } + + template <class Duration> + bool operator >( const Duration& r ) const + { return std::tr2::detail::__op_aux<milliseconds,Duration,std::greater<tick_type>,std::tr2::detail::__is_more_precise<milliseconds,Duration>::value>()( *this, r ); } + + bool operator >=( const milliseconds& r ) const + { return tv >= r.tv; } + + template <class Duration> + bool operator >=( const Duration& r ) const + { return std::tr2::detail::__op_aux<milliseconds,Duration,std::greater_equal<tick_type>,std::tr2::detail::__is_more_precise<milliseconds,Duration>::value>()( *this, r ); } + + milliseconds operator +( const milliseconds& r ) const + { return milliseconds( tv + r.tv ); } + + system_time operator +( const system_time& r ) const; + + template <class Duration> + typename std::tr2::detail::__is_more_precise<milliseconds,Duration>::finest_type operator +(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<milliseconds,Duration>::finest_type( + std::tr2::detail::__op_aux2<milliseconds,Duration,std::tr2::detail::add,std::tr2::detail::__is_more_precise<milliseconds,Duration>::value>()( *this, r ) ); + } + + milliseconds operator -( const milliseconds& r ) const + { return milliseconds( tv - r.tv ); } + + template <class Duration> + typename std::tr2::detail::__is_more_precise<milliseconds,Duration>::finest_type operator -(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<milliseconds,Duration>::finest_type( + std::tr2::detail::__op_aux2<milliseconds,Duration,std::tr2::detail::sub,std::tr2::detail::__is_more_precise<milliseconds,Duration>::value>()( *this, r ) ); + } + + milliseconds operator *( long r ) const + { return milliseconds( tv * r ); } + + microseconds operator /( long r ) const + { return milliseconds( tv / r ); } + + private: + tick_type tv; + + friend class nanoseconds; + friend class microseconds; + friend class seconds; + friend class minutes; + friend class hours; +}; + +class seconds +{ + public: + typedef std::tr2::detail::signed_tick_type tick_type; + + static const tick_type ticks_per_second; + static const tick_type seconds_per_tick; + static const bool is_subsecond; + + seconds( long long s = 0LL ) : + tv( s ) + { } + + tick_type count() const + { return tv; } + + template <typename RhsDuration> + seconds& operator -=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv -= d.tv * factor / 1000000000LL; + return *this; + } + + template <typename RhsDuration> + seconds& operator +=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv += d.tv * factor / 1000000000LL; + return *this; + } + + seconds& operator *=( long v ) + { + tv *= v; + return *this; + } + + seconds& operator /=( long v ) + { + tv /= v; + return *this; + } + + seconds operator -() const + { return seconds( -tv ); } + + operator nanoseconds() const + { return nanoseconds(tv * 1000000000LL); } + + operator microseconds() const + { return microseconds(tv * 1000000LL); } + + operator milliseconds() const + { return milliseconds(tv * 1000LL); } + + bool operator ==( const seconds& r ) const + { return tv == r.tv; } + + template <class Duration> + bool operator ==( const Duration& r ) const + { return std::tr2::detail::__op_aux<seconds,Duration,std::equal_to<tick_type>,std::tr2::detail::__is_more_precise<seconds,Duration>::value>()( *this, r ); } + + bool operator !=( const seconds& r ) const + { return tv != r.tv; } + + template <class Duration> + bool operator !=( const Duration& r ) const + { return std::tr2::detail::__op_aux<seconds,Duration,std::not_equal_to<tick_type>,std::tr2::detail::__is_more_precise<seconds,Duration>::value>()( *this, r ); } + + bool operator <( const seconds& r ) const + { return tv < r.tv; } + + template <class Duration> + bool operator <( const Duration& r ) const + { return std::tr2::detail::__op_aux<seconds,Duration,std::less<tick_type>,std::tr2::detail::__is_more_precise<seconds,Duration>::value>()( *this, r ); } + + bool operator <=( const seconds& r ) const + { return tv <= r.tv; } + + template <class Duration> + bool operator <=( const Duration& r ) const + { return std::tr2::detail::__op_aux<seconds,Duration,std::less_equal<tick_type>,std::tr2::detail::__is_more_precise<seconds,Duration>::value>()( *this, r ); } + + bool operator >( const seconds& r ) const + { return tv > r.tv; } + + template <class Duration> + bool operator >( const Duration& r ) const + { return std::tr2::detail::__op_aux<seconds,Duration,std::greater<tick_type>,std::tr2::detail::__is_more_precise<seconds,Duration>::value>()( *this, r ); } + + bool operator >=( const seconds& r ) const + { return tv >= r.tv; } + + template <class Duration> + bool operator >=( const Duration& r ) const + { return std::tr2::detail::__op_aux<seconds,Duration,std::greater_equal<tick_type>,std::tr2::detail::__is_more_precise<seconds,Duration>::value>()( *this, r ); } + + seconds operator +( const seconds& r ) const + { return seconds( tv + r.tv ); } + + system_time operator +( const system_time& r ) const; + + template <class Duration> + typename std::tr2::detail::__is_more_precise<seconds,Duration>::finest_type operator +(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<seconds,Duration>::finest_type( + std::tr2::detail::__op_aux2<seconds,Duration,std::tr2::detail::add,std::tr2::detail::__is_more_precise<seconds,Duration>::value>()( *this, r ) ); + } + + seconds operator -( const seconds& r ) const + { return seconds( tv - r.tv ); } + + template <class Duration> + typename std::tr2::detail::__is_more_precise<seconds,Duration>::finest_type operator -(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<seconds,Duration>::finest_type( + std::tr2::detail::__op_aux2<seconds,Duration,std::tr2::detail::sub,std::tr2::detail::__is_more_precise<seconds,Duration>::value>()( *this, r ) ); + } + + seconds operator *( long r ) const + { return seconds( tv * r ); } + + seconds operator /( long r ) const + { return seconds( tv / r ); } + + private: + tick_type tv; + + friend class nanoseconds; + friend class microseconds; + friend class milliseconds; + friend class minutes; + friend class hours; +}; + +class minutes +{ + public: + typedef std::tr2::detail::signed_tick_type tick_type; + + static const tick_type ticks_per_second; + static const tick_type seconds_per_tick; + static const bool is_subsecond; + + minutes( long long m = 0LL ) : + tv( m ) + { } + + tick_type count() const + { return tv; } + + template <typename RhsDuration> + minutes& operator -=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv -= d.tv * factor / 60000000000LL; + return *this; + } + + template <typename RhsDuration> + minutes& operator +=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv += d.tv * factor / 60000000000LL; + return *this; + } + + + minutes& operator *=( long v ) + { + tv *= v; + return *this; + } + + minutes& operator /=( long v ) + { + tv /= v; + return *this; + } + + minutes operator-() const + { return minutes( -tv ); } + + operator nanoseconds() const + { return nanoseconds(tv * 60000000000LL); } + + operator microseconds() const + { return microseconds(tv * 60000000LL); } + + operator milliseconds() const + { return milliseconds(tv * 60000LL); } + + operator seconds() const + { return seconds(tv * 60LL); } + + bool operator ==( const minutes& r ) const + { return tv == r.tv; } + + template <class Duration> + bool operator ==( const Duration& r ) const + { return std::tr2::detail::__op_aux<minutes,Duration,std::equal_to<tick_type>,std::tr2::detail::__is_more_precise<minutes,Duration>::value>()( *this, r ); } + + bool operator !=( const minutes& r ) const + { return tv != r.tv; } + + template <class Duration> + bool operator !=( const Duration& r ) const + { return std::tr2::detail::__op_aux<minutes,Duration,std::not_equal_to<tick_type>,std::tr2::detail::__is_more_precise<minutes,Duration>::value>()( *this, r ); } + + bool operator <( const minutes& r ) const + { return tv < r.tv; } + + template <class Duration> + bool operator <( const Duration& r ) const + { return std::tr2::detail::__op_aux<minutes,Duration,std::less<tick_type>,std::tr2::detail::__is_more_precise<minutes,Duration>::value>()( *this, r ); } + + bool operator <=( const minutes& r ) const + { return tv <= r.tv; } + + template <class Duration> + bool operator <=( const Duration& r ) const + { return std::tr2::detail::__op_aux<minutes,Duration,std::less_equal<tick_type>,std::tr2::detail::__is_more_precise<minutes,Duration>::value>()( *this, r ); } + + bool operator >( const minutes& r ) const + { return tv > r.tv; } + + template <class Duration> + bool operator >( const Duration& r ) const + { return std::tr2::detail::__op_aux<minutes,Duration,std::greater<tick_type>,std::tr2::detail::__is_more_precise<minutes,Duration>::value>()( *this, r ); } + + bool operator >=( const minutes& r ) const + { return tv >= r.tv; } + + template <class Duration> + bool operator >=( const Duration& r ) const + { return std::tr2::detail::__op_aux<minutes,Duration,std::greater_equal<tick_type>,std::tr2::detail::__is_more_precise<minutes,Duration>::value>()( *this, r ); } + + minutes operator +( const minutes& r ) const + { return minutes( tv + r.tv ); } + + system_time operator +( const system_time& r ) const; + + template <class Duration> + typename std::tr2::detail::__is_more_precise<minutes,Duration>::finest_type operator +(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<minutes,Duration>::finest_type( + std::tr2::detail::__op_aux2<minutes,Duration,std::tr2::detail::add,std::tr2::detail::__is_more_precise<minutes,Duration>::value>()( *this, r ) ); + } + + minutes operator -( const minutes& r ) const + { return minutes( tv - r.tv ); } + + template <class Duration> + typename std::tr2::detail::__is_more_precise<minutes,Duration>::finest_type operator -(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<minutes,Duration>::finest_type( + std::tr2::detail::__op_aux2<minutes,Duration,std::tr2::detail::sub,std::tr2::detail::__is_more_precise<minutes,Duration>::value>()( *this, r ) ); + } + + minutes operator *( long r ) const + { return minutes( tv * r ); } + + minutes operator /( long r ) const + { return minutes( tv / r ); } + + private: + tick_type tv; + + friend class nanoseconds; + friend class microseconds; + friend class milliseconds; + friend class seconds; + friend class hours; +}; + +class hours +{ + public: + typedef std::tr2::detail::signed_tick_type tick_type; + + static const tick_type ticks_per_second; + static const tick_type seconds_per_tick; + static const bool is_subsecond; + + hours( long long h = 0LL ) : + tv( h ) + { } + + tick_type count() const + { return tv; } + + template <typename RhsDuration> + hours& operator -=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv -= d.tv * factor / 3600000000000LL; + return *this; + } + + template <typename RhsDuration> + hours& operator +=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv += d.tv * factor / 3600000000000LL; + return *this; + } + + hours& operator *=( long v ) + { + tv *= v; + return *this; + } + + hours& operator /=( long v ) + { + tv /= v; + return *this; + } + + hours operator -() const + { return hours( -tv ); } + + operator nanoseconds() const + { return nanoseconds(tv * 3600000000000LL); } + + operator microseconds() const + { return microseconds(tv * 3600000000LL); } + + operator milliseconds() const + { return milliseconds(tv * 3600000LL); } + + operator seconds() const + { return seconds(tv * 3600LL); } + + operator minutes() const + { return minutes(tv * 60LL); } + + bool operator ==( const hours& r ) const + { return tv == r.tv; } + + template <class Duration> + bool operator ==( const Duration& r ) const + { return std::tr2::detail::__op_aux<hours,Duration,std::equal_to<tick_type>,std::tr2::detail::__is_more_precise<hours,Duration>::value>()( *this, r ); } + + bool operator !=( const hours& r ) const + { return tv != r.tv; } + + template <class Duration> + bool operator !=( const Duration& r ) const + { return std::tr2::detail::__op_aux<hours,Duration,std::not_equal_to<tick_type>,std::tr2::detail::__is_more_precise<hours,Duration>::value>()( *this, r ); } + + bool operator <( const hours& r ) const + { return tv < r.tv; } + + template <class Duration> + bool operator <( const Duration& r ) const + { return std::tr2::detail::__op_aux<hours,Duration,std::less<tick_type>,std::tr2::detail::__is_more_precise<hours,Duration>::value>()( *this, r ); } + + bool operator <=( const hours& r ) const + { return tv <= r.tv; } + + template <class Duration> + bool operator <=( const Duration& r ) const + { return std::tr2::detail::__op_aux<hours,Duration,std::less_equal<tick_type>,std::tr2::detail::__is_more_precise<hours,Duration>::value>()( *this, r ); } + + bool operator >( const hours& r ) const + { return tv > r.tv; } + + template <class Duration> + bool operator >( const Duration& r ) const + { return std::tr2::detail::__op_aux<hours,Duration,std::greater<tick_type>,std::tr2::detail::__is_more_precise<hours,Duration>::value>()( *this, r ); } + + bool operator >=( const hours& r ) const + { return tv >= r.tv; } + + template <class Duration> + bool operator >=( const Duration& r ) const + { return std::tr2::detail::__op_aux<hours,Duration,std::greater_equal<tick_type>,std::tr2::detail::__is_more_precise<hours,Duration>::value>()( *this, r ); } + + hours operator +( const hours& r ) const + { return hours( tv + r.tv ); } + + system_time operator +( const system_time& r ) const; + + template <class Duration> + typename std::tr2::detail::__is_more_precise<hours,Duration>::finest_type operator +(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<hours,Duration>::finest_type( + std::tr2::detail::__op_aux2<hours,Duration,std::tr2::detail::add,std::tr2::detail::__is_more_precise<hours,Duration>::value>()( *this, r ) ); + } + + hours operator -( const hours& r ) const + { return hours( tv - r.tv ); } + + template <class Duration> + typename std::tr2::detail::__is_more_precise<hours,Duration>::finest_type operator -(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<hours,Duration>::finest_type( + std::tr2::detail::__op_aux2<hours,Duration,std::tr2::detail::sub,std::tr2::detail::__is_more_precise<hours,Duration>::value>()( *this, r ) ); + } + + hours operator *( long r ) const + { return hours( tv * r ); } + + hours operator /( long r ) const + { return hours( tv / r ); } + + private: + tick_type tv; + + friend class nanoseconds; + friend class microseconds; + friend class milliseconds; + friend class seconds; + friend class minutes; +}; + +system_time get_system_time(); + +class system_time +{ + private: + struct _adopt_t {}; + + public: + typedef std::tr2::detail::unsigned_tick_type tick_type; + + static const tick_type ticks_per_second; + static const tick_type seconds_per_tick; + static const bool is_subsecond; + + system_time() : + tv( 0ULL ) + { } + explicit system_time( time_t t, nanoseconds ns ) : + tv( t * ticks_per_second + ns.count() ) + { } + explicit system_time( time_t t ) : + tv( t * ticks_per_second ) + { } + + time_t seconds_since_epoch() const + { return static_cast<time_t>( tv / nanoseconds::ticks_per_second ); } + + nanoseconds nanoseconds_since_epoch() const + { return nanoseconds( tv ); } + + bool operator ==(const system_time& rhs) const + { return tv == rhs.tv; } + + bool operator !=(const system_time& rhs) const + { return tv != rhs.tv; } + + bool operator >(const system_time& rhs) const + { return tv > rhs.tv; } + + bool operator >=(const system_time& rhs) const + { return tv >= rhs.tv; } + + bool operator <(const system_time& rhs) const + { return tv < rhs.tv; } + + bool operator <=(const system_time& rhs) const + { return tv <= rhs.tv; } + + nanoseconds operator -(const system_time& rhs) const + { return nanoseconds( tv - rhs.tv ); } + + system_time operator +(const nanoseconds& td) const + { return system_time( tv + td.count(), _adopt_t() ); } + + template <typename Duration> + system_time operator +(const Duration& td) const + { return system_time( tv + static_cast<nanoseconds>( td ).count(), _adopt_t() ); } + + system_time& operator +=(const nanoseconds& td) + { + tv += td.count(); + + return *this; + } + + template <typename Duration> + system_time& operator +=(const Duration& td) + { + tv += static_cast<nanoseconds>( td ).count(); + + return *this; + } + + system_time operator -(const nanoseconds& td) const + { return system_time( tv - td.count() ); } + + template <typename Duration> + system_time operator -(const Duration& td) const + { return system_time( tv - static_cast<nanoseconds>( td ).count() ); } + + system_time& operator -=(const nanoseconds& td) + { + tv -= td.count(); + + return *this; + } + + template <typename Duration> + system_time& operator -=(const Duration& td) + { + tv -= static_cast<nanoseconds>( td ).count(); + + return *this; + } + + private: + system_time( tick_type _v, const _adopt_t& ) : + tv( _v ) + { } + + tick_type tv; + + friend system_time get_system_time(); +}; + +inline nanoseconds operator *( long lhs, const nanoseconds& rhs ) +{ return nanoseconds( rhs.count() * lhs ); } + +inline microseconds operator *( long lhs, const microseconds& rhs ) +{ return microseconds( rhs.count() * lhs ); } + +inline milliseconds operator *( long lhs, const milliseconds& rhs ) +{ return milliseconds( rhs.count() * lhs ); } + +inline seconds operator *( long lhs, const seconds& rhs ) +{ return seconds( rhs.count() * lhs ); } + +inline minutes operator *( long lhs, const minutes& rhs ) +{ return minutes( rhs.count() * lhs ); } + +inline hours operator *( long lhs, const hours& rhs ) +{ return hours( rhs.count() * lhs ); } + +} // namespace tr2 + +} // namespace std + +#endif // __MT_DATE_TIME Copied: trunk/complement/explore/include/mt/mutex (from rev 1821, branches/wg21-thread/include/mt/mutex) =================================================================== --- trunk/complement/explore/include/mt/mutex (rev 0) +++ trunk/complement/explore/include/mt/mutex 2008-02-27 16:44:54 UTC (rev 1822) @@ -0,0 +1,893 @@ +// -*- C++ -*- Time-stamp: <08/02/24 23:48:23 ptr> + +/* + * Copyright (c) 1997-1999, 2002-2008 + * Petr Ovtchenkov + * + * Portion Copyright (c) 1999-2001 + * Parallel Graphics Ltd. + * + * Licensed under the Academic Free License version 3.0 + * + * Derived from original <mt/xmt.h> of 'complement' project + * [http://complement.sourceforge.net] + * to make it close to JTC1/SC22/WG21 working draft + * [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2497.html] + */ + +#ifndef __MUTEX_H +#define __MUTEX_H + +#ifndef __config_feature_h +#include <config/feature.h> +#endif + +#include <cstddef> +#include <stdexcept> + +#ifdef WIN32 +# include <windows.h> +# include <memory> +# include <limits> +# define ETIME 62 /* timer expired */ +# pragma warning( disable : 4290) +#endif // WIN32 + +#ifdef __unix +# include <pthread.h> +# include <sched.h> +#endif // __unix + +#include <cerrno> +#include <mt/system_error> + +namespace std { + +namespace tr2 { + +class lock_error : + public std::exception +{ + private: + int r_; + + public: + + explicit lock_error( int r ) : + r_( r ) + { } + + virtual char const *what() throw() + { return "std::lock_error"; } + + int error() const + { return r_; } +}; + +namespace detail { + +#ifdef __FIT_PSHARED_MUTEX +extern std::string _notpshared; +#endif + +#ifdef __FIT_XSI_THR +extern std::string _notrecursive; +#endif + +} // namespace detail + +template <bool SCOPE> class __condition_variable; +template <bool SCOPE> class __condition_variable_any; +template <bool SCOPE> class __condition_event; + +// if parameter SCOPE (process scope) true, PTHREAD_PROCESS_SHARED will +// be used; otherwise PTHREAD_PROCESS_PRIVATE. +// Of cause, system must support process scope... +// Linux at 2003-01-19 NOT SUPPORT PTHREAD_PROCESS_SHARED mutex! +// And Windows too! +// +template <bool RECURSIVE_SAFE, bool SCOPE> +class __mutex_base +{ + public: + __mutex_base() + { +#ifdef __FIT_PTHREADS + if ( SCOPE || RECURSIVE_SAFE ) { + pthread_mutexattr_t att; + pthread_mutexattr_init( &att ); +# ifdef __FIT_PSHARED_MUTEX + if ( SCOPE ) { + if ( pthread_mutexattr_setpshared( &att, PTHREAD_PROCESS_SHARED ) != 0 ) { + throw std::invalid_argument( detail::_notpshared ); + } + } +# endif // __FIT_PSHARED_MUTEX +# ifdef __FIT_XSI_THR // Unix 98 or X/Open System Interfaces Extention + if ( RECURSIVE_SAFE ) { + if ( pthread_mutexattr_settype( &att, PTHREAD_MUTEX_RECURSIVE ) != 0 ) { + throw std::invalid_argument( detail::_notrecursive ); + } + } +# endif + pthread_mutex_init( &_M_lock, &att ); + pthread_mutexattr_destroy( &att ); + } else { + pthread_mutex_init( &_M_lock, 0 ); + } +#endif // _PTHREADS +#ifdef __FIT_WIN32THREADS + InitializeCriticalSection( &_M_lock ); +#endif + } + + ~_... [truncated message content] |
From: <com...@us...> - 2008-02-27 14:22:56
|
Revision: 1821 http://complement.svn.sourceforge.net/complement/?rev=1821&view=rev Author: complement Date: 2008-02-27 06:22:44 -0800 (Wed, 27 Feb 2008) Log Message: ----------- use general solution Modified Paths: -------------- trunk/complement/explore/app/exam/doc/requirements/Makefile Modified: trunk/complement/explore/app/exam/doc/requirements/Makefile =================================================================== --- trunk/complement/explore/app/exam/doc/requirements/Makefile 2008-02-27 14:18:59 UTC (rev 1820) +++ trunk/complement/explore/app/exam/doc/requirements/Makefile 2008-02-27 14:22:44 UTC (rev 1821) @@ -1,3 +1,13 @@ +# Time-stamp: <08/01/08 15:20:25 ptr> +# +# Copyright (c) 2007,2008 +# Petr Ovtchenkov +# +# Licensed under the Academic Free License version 3.0 +# + +SRCROOT := ../../../.. + PDFNAMES = ExamUseCaseSpec ExamUseCaseSpec_SRC_TEX = ExamUseCaseSpec.tex @@ -3,59 +13,3 @@ ExamUseCaseSpec_SRC_FIG = p1.fig p2.fig p3.fig p4.fig p5.fig debug-focus.fig -all: $(addsuffix .pdf,$(PDFNAMES)) - -OUTDIR = .out - -PDF_DIR_SRC = -FIG_BASE = -define pdf_ -PDF_DIR_SRC += $$(dir $${$(1)_SRC_TEX} $${$(1)_SRC_FIG} ) -FIG_BASE += $$(basename $${$(1)_SRC_FIG}) -$(1)_ALLMP := $$(addsuffix .mp,$$(basename $${$(1)_SRC_FIG} ) ) -$(1)_ALLMPS := $$(addsuffix .mps,$$(basename $${$(1)_SRC_FIG} ) ) -$(1)_ALL0 := $$(addsuffix .0,$$(basename $${$(1)_SRC_FIG} ) ) - -$(1)_MP := $$(addprefix $$(OUTDIR)/,$${$(1)_ALLMP}) -$(1)_MPS := $$($(1)_ALLMPS) -$(1)_0 := $$(addprefix $$(OUTDIR)/,$${$(1)_ALL0}) - -$(1).pdf: $$($(1)_SRC_TEX) $$($(1)_MPS) - pdflatex $$< -endef - -$(foreach pdf,$(PDFNAMES),$(eval $(call pdf_,$(pdf)))) - -# if sources disposed in several dirs, calculate appropriate rules - -DIRS_UNIQUE_SRC := $(dir $(SRC_FIG) $(SRC_TEX) ) -DIRS_UNIQUE_SRC := $(sort $(DIRS_UNIQUE_SRC) $(PDF_DIR_SRC)) - - -define rule_mp -$$(OUTDIR$(1))/%.mp: $(2)%.fig - $$(chdirs) - fig2dev -L mp $$< $$@ -endef - -define rule_mps -$(1).mps: $$(OUTDIR)/$(1).0 - ln -sf $$< $$@ - -$$(OUTDIR)/$(1).0: $$(OUTDIR)/$(1).mp - (cd ${OUTDIR}; mpost `basename $$<`) -endef - -define rules_m_ -$(call rule_mp,,$(1)) -endef - -$(foreach mps,${FIG_BASE},$(eval $(call rule_mps,$$(notdir $(mps))))) - -$(foreach dir,$(DIRS_UNIQUE_SRC),$(eval $(call rules_m_,$(dir)))) - -define chdirs -if [ ! -d ${OUTDIR} ]; then \ - mkdir -p ${OUTDIR}; \ -fi -endef - +include $(SRCROOT)/Makefiles/gmake/topdoc.mak This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-02-27 14:19:09
|
Revision: 1820 http://complement.svn.sourceforge.net/complement/?rev=1820&view=rev Author: complement Date: 2008-02-27 06:18:59 -0800 (Wed, 27 Feb 2008) Log Message: ----------- a lot of tests for type_traits Modified Paths: -------------- trunk/complement/explore/lib/misc/ut/Makefile trunk/complement/explore/lib/misc/ut/misc_test.cc trunk/complement/explore/lib/misc/ut/misc_test.h trunk/complement/explore/lib/misc/ut/misc_test_suite.cc Modified: trunk/complement/explore/lib/misc/ut/Makefile =================================================================== --- trunk/complement/explore/lib/misc/ut/Makefile 2008-02-27 14:18:00 UTC (rev 1819) +++ trunk/complement/explore/lib/misc/ut/Makefile 2008-02-27 14:18:59 UTC (rev 1820) @@ -1,4 +1,4 @@ -# -*- Makefile -*- Time-stamp: <07/08/06 10:19:59 ptr> +# -*- Makefile -*- Time-stamp: <07/11/23 23:30:57 ptr> SRCROOT := ../../.. @@ -10,15 +10,16 @@ DEFS += -D__FIT_EXAM LIBEXAM_DIR = ${CoMT_DIR}/lib/exam +LIBXMT_DIR = ${CoMT_DIR}/lib/mt ifeq ($(OSNAME),linux) -release-shared: LDSEARCH += -L${LIBEXAM_DIR}/${OUTPUT_DIR} -Wl,--rpath=${LIBEXAM_DIR}/${OUTPUT_DIR}:${STLPORT_LIB_DIR} +release-shared: LDSEARCH += -L${LIBEXAM_DIR}/${OUTPUT_DIR} -L${LIBXMT_DIR}/${OUTPUT_DIR} -Wl,--rpath=${LIBEXAM_DIR}/${OUTPUT_DIR}:${LIBXMT_DIR}/${OUTPUT_DIR}:${STLPORT_LIB_DIR} -dbg-shared: LDSEARCH += -L${LIBEXAM_DIR}/${OUTPUT_DIR_DBG} -Wl,--rpath=${LIBEXAM_DIR}/${OUTPUT_DIR_DBG}:${STLPORT_LIB_DIR} +dbg-shared: LDSEARCH += -L${LIBEXAM_DIR}/${OUTPUT_DIR_DBG} -L${LIBXMT_DIR}/${OUTPUT_DIR_DBG} -Wl,--rpath=${LIBEXAM_DIR}/${OUTPUT_DIR_DBG}:${LIBXMT_DIR}/${OUTPUT_DIR_DBG}:${STLPORT_LIB_DIR} ifndef WITHOUT_STLPORT -stldbg-shared: LDSEARCH += -L${LIBEXAM_DIR}/${OUTPUT_DIR_STLDBG} -Wl,--rpath=${LIBEXAM_DIR}/${OUTPUT_DIR_STLDBG}:${STLPORT_LIB_DIR} +stldbg-shared: LDSEARCH += -L${LIBEXAM_DIR}/${OUTPUT_DIR_STLDBG} -L${LIBXMT_DIR}/${OUTPUT_DIR_STLDBG} -Wl,--rpath=${LIBEXAM_DIR}/${OUTPUT_DIR_STLDBG}:${LIBXMT_DIR}/${OUTPUT_DIR_STLDBG}:${STLPORT_LIB_DIR} endif endif @@ -35,10 +36,10 @@ endif -release-shared : LDLIBS = -lexam -dbg-shared : LDLIBS = -lexamg +release-shared : LDLIBS = -lexam -lxmt +dbg-shared : LDLIBS = -lexamg -lxmtg ifndef WITHOUT_STLPORT -stldbg-shared : LDLIBS = -lexamstlg +stldbg-shared : LDLIBS = -lexamstlg -lxmtstlg endif ifeq ($(OSNAME),freebsd) Modified: trunk/complement/explore/lib/misc/ut/misc_test.cc =================================================================== --- trunk/complement/explore/lib/misc/ut/misc_test.cc 2008-02-27 14:18:00 UTC (rev 1819) +++ trunk/complement/explore/lib/misc/ut/misc_test.cc 2008-02-27 14:18:59 UTC (rev 1820) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <07/08/06 10:26:25 ptr> +// -*- C++ -*- Time-stamp: <07/12/02 20:37:29 ptr> /* * Copyright (c) 2007 @@ -34,6 +34,22 @@ int n; }; +class MyTypeF +{ + public: + int f() + { return 0; } + virtual int g() + { return 0; } + static int h() + { return 0; } + + int a; + static int b; +}; + +int MyTypeF::b = 0; + int f() { return 0; @@ -60,6 +76,452 @@ return EXAM_RESULT; } +int EXAM_IMPL(misc_test::type_traits_is_void) +{ + EXAM_CHECK( std::tr1::is_void<void>::value == true ); + EXAM_CHECK( std::tr1::is_void<int>::value == false ); + + return EXAM_RESULT; +} + +int EXAM_IMPL(misc_test::type_traits_is_integral) +{ + EXAM_CHECK( std::tr1::is_integral<bool>::value == true ); + EXAM_CHECK( std::tr1::is_integral<char>::value == true ); + EXAM_CHECK( std::tr1::is_integral<wchar_t>::value == true ); + EXAM_CHECK( std::tr1::is_integral<signed char>::value == true ); + EXAM_CHECK( std::tr1::is_integral<unsigned char>::value == true ); + EXAM_CHECK( std::tr1::is_integral<short>::value == true ); + EXAM_CHECK( std::tr1::is_integral<unsigned short>::value == true ); + EXAM_CHECK( std::tr1::is_integral<int>::value == true ); + EXAM_CHECK( std::tr1::is_integral<unsigned int>::value == true ); + EXAM_CHECK( std::tr1::is_integral<long>::value == true ); + EXAM_CHECK( std::tr1::is_integral<unsigned long>::value == true ); + EXAM_CHECK( std::tr1::is_integral<long long>::value == true ); + EXAM_CHECK( std::tr1::is_integral<unsigned long long>::value == true ); + + EXAM_CHECK( std::tr1::is_integral<void>::value == false ); + EXAM_CHECK( std::tr1::is_integral<double>::value == false ); + EXAM_CHECK( std::tr1::is_integral<MyType>::value == false ); + EXAM_CHECK( std::tr1::is_integral<MyTypeOther>::value == false ); + + EXAM_CHECK( std::tr1::is_integral<const bool>::value == true ); + EXAM_CHECK( std::tr1::is_integral<volatile bool>::value == true ); + EXAM_CHECK( std::tr1::is_integral<const volatile bool>::value == true ); + + return EXAM_RESULT; +} + +int EXAM_IMPL(misc_test::type_traits_is_floating_point) +{ + EXAM_CHECK( std::tr1::is_floating_point<float>::value == true ); + EXAM_CHECK( std::tr1::is_floating_point<double>::value == true ); + EXAM_CHECK( std::tr1::is_floating_point<long double>::value == true ); + + EXAM_CHECK( std::tr1::is_floating_point<int>::value == false ); + EXAM_CHECK( std::tr1::is_floating_point<MyType>::value == false ); + EXAM_CHECK( std::tr1::is_floating_point<MyTypeOther>::value == false ); + + EXAM_CHECK( std::tr1::is_floating_point<const double>::value == true ); + EXAM_CHECK( std::tr1::is_floating_point<volatile double>::value == true ); + EXAM_CHECK( std::tr1::is_floating_point<const volatile double>::value == true ); + + return EXAM_RESULT; +} + +int EXAM_IMPL(misc_test::type_traits_is_array) +{ + EXAM_CHECK( std::tr1::is_array<int [5]>::value == true ); + EXAM_CHECK( std::tr1::is_array<int []>::value == true ); + EXAM_CHECK( std::tr1::is_array<MyTypeOther []>::value == true ); + + EXAM_CHECK( std::tr1::is_array<int>::value == false ); + EXAM_CHECK( std::tr1::is_array<int *>::value == false ); + + return EXAM_RESULT; +} + +int EXAM_IMPL(misc_test::type_traits_is_pointer) +{ + EXAM_CHECK( std::tr1::is_pointer<int *>::value == true ); + EXAM_CHECK( std::tr1::is_pointer<MyType *>::value == true ); + EXAM_CHECK( std::tr1::is_pointer<MyTypeOther *>::value == true ); + EXAM_CHECK( std::tr1::is_pointer<int (*)()>::value == true ); + + EXAM_CHECK( std::tr1::is_pointer<int>::value == false ); + EXAM_CHECK( std::tr1::is_pointer<int []>::value == false ); + EXAM_CHECK( std::tr1::is_pointer<int (MyTypeF::*)()>::value == false ); + + return EXAM_RESULT; +} + +int EXAM_IMPL(misc_test::type_traits_is_lvalue_reference) +{ + EXAM_CHECK( std::tr1::is_lvalue_reference<int &>::value == true ); + EXAM_CHECK( std::tr1::is_lvalue_reference<int (&)(void)>::value == true ); + + // EXAM_CHECK( std::tr1::is_lvalue_reference<int &&>::value == false ); + EXAM_CHECK( std::tr1::is_lvalue_reference<int>::value == false ); + EXAM_CHECK( std::tr1::is_lvalue_reference<int *>::value == false ); + + return EXAM_RESULT; +} + +/* +int EXAM_IMPL(misc_test::type_traits_is_rvalue_reference) +{ + EXAM_CHECK( std::tr1::is_rvalue_reference<int &&>::value == true ); + + EXAM_CHECK( std::tr1::is_rvalue_reference<int &>::value == false ); + EXAM_CHECK( std::tr1::is_rvalue_reference<int>::value == false ); + EXAM_CHECK( std::tr1::is_rvalue_reference<int *>::value == false ); + EXAM_CHECK( std::tr1::is_rvalue_reference<int (&)()>::value == false ); + + return EXAM_RESULT; +} +*/ + +int EXAM_IMPL(misc_test::type_traits_is_member_object_pointer) +{ + EXAM_CHECK( std::tr1::is_member_object_pointer<int (MyTypeF::*)>::value == true ); + + EXAM_CHECK( std::tr1::is_member_object_pointer<int (MyTypeF::*)()>::value == false ); + EXAM_CHECK( std::tr1::is_member_object_pointer<int *>::value == false ); + EXAM_CHECK( std::tr1::is_member_object_pointer<int (*)()>::value == false ); + + return EXAM_RESULT; +} + +int EXAM_IMPL(misc_test::type_traits_is_member_function_pointer) +{ + EXAM_CHECK( std::tr1::is_member_function_pointer<int (MyTypeF::*)()>::value == true ); + + EXAM_CHECK( std::tr1::is_member_function_pointer<int (MyTypeF::*)>::value == false ); + EXAM_CHECK( std::tr1::is_member_function_pointer<int *>::value == false ); + EXAM_CHECK( std::tr1::is_member_function_pointer<int (*)()>::value == false ); + EXAM_CHECK( std::tr1::is_member_function_pointer<int (&)()>::value == false ); + + return EXAM_RESULT; +} + +enum enum_type { one, two, three }; + +int EXAM_IMPL(misc_test::type_traits_is_enum) +{ + EXAM_CHECK( std::tr1::is_enum<enum_type>::value == true ); + + EXAM_CHECK( std::tr1::is_enum<int>::value == false ); + EXAM_CHECK( std::tr1::is_enum<char>::value == false ); + + return EXAM_RESULT; +} + +union union_type +{ + int a; + char c; +}; + +struct structure_type +{ + int a; + char c; +}; + +class class_type +{ + int a; + char c; +}; + + +int EXAM_IMPL(misc_test::type_traits_is_union) +{ + // EXAM_CHECK( std::tr1::is_union<union_type>::value == true ); + + // EXAM_CHECK( std::tr1::is_union<structure_type>::value == false ); + // EXAM_CHECK( std::tr1::is_union<class_type>::value == false ); + + return EXAM_RESULT; +} + +int EXAM_IMPL(misc_test::type_traits_is_class) +{ + // EXAM_CHECK( std::tr1::is_class<structure_type>::value == true ); + // EXAM_CHECK( std::tr1::is_class<class_type>::value == true ); + + // EXAM_CHECK( std::tr1::is_class<union_type>::value == false ); + + return EXAM_RESULT; +} + +int EXAM_IMPL(misc_test::type_traits_is_function) +{ + EXAM_CHECK( std::tr1::is_function<int (void)>::value == true ); + EXAM_CHECK( std::tr1::is_function<int (int)>::value == true ); + + EXAM_CHECK( std::tr1::is_function<int (&)()>::value == false ); + EXAM_CHECK( std::tr1::is_function<int (*)()>::value == false ); + + return EXAM_RESULT; +} + +int EXAM_IMPL(misc_test::type_traits_is_reference) +{ + EXAM_CHECK( std::tr1::is_reference<int &>::value == true ); + EXAM_CHECK( std::tr1::is_reference<int (&)(void)>::value == true ); + + EXAM_CHECK( std::tr1::is_reference<int>::value == false ); + EXAM_CHECK( std::tr1::is_reference<int *>::value == false ); + + return EXAM_RESULT; +} + +int EXAM_IMPL(misc_test::type_traits_is_arithmetic) +{ + EXAM_CHECK( std::tr1::is_arithmetic<bool>::value == true ); + EXAM_CHECK( std::tr1::is_arithmetic<char>::value == true ); + EXAM_CHECK( std::tr1::is_arithmetic<wchar_t>::value == true ); + EXAM_CHECK( std::tr1::is_arithmetic<signed char>::value == true ); + EXAM_CHECK( std::tr1::is_arithmetic<unsigned char>::value == true ); + EXAM_CHECK( std::tr1::is_arithmetic<short>::value == true ); + EXAM_CHECK( std::tr1::is_arithmetic<unsigned short>::value == true ); + EXAM_CHECK( std::tr1::is_arithmetic<int>::value == true ); + EXAM_CHECK( std::tr1::is_arithmetic<unsigned int>::value == true ); + EXAM_CHECK( std::tr1::is_arithmetic<long>::value == true ); + EXAM_CHECK( std::tr1::is_arithmetic<unsigned long>::value == true ); + EXAM_CHECK( std::tr1::is_arithmetic<long long>::value == true ); + EXAM_CHECK( std::tr1::is_arithmetic<unsigned long long>::value == true ); + EXAM_CHECK( std::tr1::is_arithmetic<float>::value == true ); + EXAM_CHECK( std::tr1::is_arithmetic<double>::value == true ); + EXAM_CHECK( std::tr1::is_arithmetic<long double>::value == true ); + + EXAM_CHECK( std::tr1::is_arithmetic<enum_type>::value == false ); + EXAM_CHECK( std::tr1::is_arithmetic<int *>::value == false ); + EXAM_CHECK( std::tr1::is_arithmetic<MyTypeOther>::value == false ); + EXAM_CHECK( std::tr1::is_arithmetic<int &>::value == false ); + + return EXAM_RESULT; +} + +int EXAM_IMPL(misc_test::type_traits_is_fundamental) +{ + EXAM_CHECK( std::tr1::is_fundamental<bool>::value == true ); + EXAM_CHECK( std::tr1::is_fundamental<char>::value == true ); + EXAM_CHECK( std::tr1::is_fundamental<wchar_t>::value == true ); + EXAM_CHECK( std::tr1::is_fundamental<signed char>::value == true ); + EXAM_CHECK( std::tr1::is_fundamental<unsigned char>::value == true ); + EXAM_CHECK( std::tr1::is_fundamental<short>::value == true ); + EXAM_CHECK( std::tr1::is_fundamental<unsigned short>::value == true ); + EXAM_CHECK( std::tr1::is_fundamental<int>::value == true ); + EXAM_CHECK( std::tr1::is_fundamental<unsigned int>::value == true ); + EXAM_CHECK( std::tr1::is_fundamental<long>::value == true ); + EXAM_CHECK( std::tr1::is_fundamental<unsigned long>::value == true ); + EXAM_CHECK( std::tr1::is_fundamental<long long>::value == true ); + EXAM_CHECK( std::tr1::is_fundamental<unsigned long long>::value == true ); + EXAM_CHECK( std::tr1::is_fundamental<float>::value == true ); + EXAM_CHECK( std::tr1::is_fundamental<double>::value == true ); + EXAM_CHECK( std::tr1::is_fundamental<long double>::value == true ); + EXAM_CHECK( std::tr1::is_fundamental<void>::value == true ); + + EXAM_CHECK( std::tr1::is_fundamental<enum_type>::value == false ); + EXAM_CHECK( std::tr1::is_fundamental<int *>::value == false ); + EXAM_CHECK( std::tr1::is_fundamental<MyTypeOther>::value == false ); + EXAM_CHECK( std::tr1::is_fundamental<int &>::value == false ); + + return EXAM_RESULT; +} + +int EXAM_IMPL(misc_test::type_traits_is_object) +{ + EXAM_CHECK( std::tr1::is_object<int>::value == true ); + EXAM_CHECK( std::tr1::is_object<MyTypeOther>::value == true ); + EXAM_CHECK( std::tr1::is_object<int*>::value == true ); + EXAM_CHECK( std::tr1::is_object<int (*)()>::value == true ); + EXAM_CHECK( std::tr1::is_object<int (MyTypeF::*)()>::value == true ); + EXAM_CHECK( std::tr1::is_object<int (MyTypeF::*)>::value == true ); + + EXAM_CHECK( std::tr1::is_object<int (void)>::value == false ); + EXAM_CHECK( std::tr1::is_object<int&>::value == false ); + EXAM_CHECK( std::tr1::is_object<void>::value == false ); + EXAM_CHECK( std::tr1::is_object<enum_type>::value == false ); + EXAM_CHECK( std::tr1::is_object<int (&)()>::value == false ); + + return EXAM_RESULT; +} + +int EXAM_IMPL(misc_test::type_traits_is_scalar) +{ + EXAM_CHECK( std::tr1::is_scalar<int>::value == true ); + EXAM_CHECK( std::tr1::is_scalar<int*>::value == true ); + EXAM_CHECK( std::tr1::is_scalar<int (MyTypeF::*)()>::value == true ); + EXAM_CHECK( std::tr1::is_scalar<int (*)()>::value == true ); + EXAM_CHECK( std::tr1::is_scalar<enum_type>::value == true ); + + EXAM_CHECK( std::tr1::is_scalar<MyTypeOther>::value == false ); + EXAM_CHECK( std::tr1::is_scalar<int (void)>::value == false ); + EXAM_CHECK( std::tr1::is_scalar<int&>::value == false ); + EXAM_CHECK( std::tr1::is_scalar<void>::value == false ); + + return EXAM_RESULT; +} + +int EXAM_IMPL(misc_test::type_traits_is_compound) +{ + EXAM_CHECK( std::tr1::is_compound<enum_type>::value == true ); + EXAM_CHECK( std::tr1::is_compound<int *>::value == true ); + EXAM_CHECK( std::tr1::is_compound<MyTypeOther>::value == true ); + EXAM_CHECK( std::tr1::is_compound<int &>::value == true ); + EXAM_CHECK( std::tr1::is_compound<int (*)()>::value == true ); + EXAM_CHECK( std::tr1::is_compound<int (&)()>::value == true ); + EXAM_CHECK( std::tr1::is_compound<int (MyTypeF::*)()>::value == true ); + EXAM_CHECK( std::tr1::is_compound<int (void)>::value == true ); + + EXAM_CHECK( std::tr1::is_compound<bool>::value == false ); + EXAM_CHECK( std::tr1::is_compound<char>::value == false ); + EXAM_CHECK( std::tr1::is_compound<wchar_t>::value == false ); + EXAM_CHECK( std::tr1::is_compound<signed char>::value == false ); + EXAM_CHECK( std::tr1::is_compound<unsigned char>::value == false ); + EXAM_CHECK( std::tr1::is_compound<short>::value == false ); + EXAM_CHECK( std::tr1::is_compound<unsigned short>::value == false ); + EXAM_CHECK( std::tr1::is_compound<int>::value == false ); + EXAM_CHECK( std::tr1::is_compound<unsigned int>::value == false ); + EXAM_CHECK( std::tr1::is_compound<long>::value == false ); + EXAM_CHECK( std::tr1::is_compound<unsigned long>::value == false ); + EXAM_CHECK( std::tr1::is_compound<long long>::value == false ); + EXAM_CHECK( std::tr1::is_compound<unsigned long long>::value == false ); + EXAM_CHECK( std::tr1::is_compound<float>::value == false ); + EXAM_CHECK( std::tr1::is_compound<double>::value == false ); + EXAM_CHECK( std::tr1::is_compound<long double>::value == false ); + EXAM_CHECK( std::tr1::is_compound<void>::value == false ); + + return EXAM_RESULT; +} + +int EXAM_IMPL(misc_test::type_traits_is_member_pointer) +{ + EXAM_CHECK( std::tr1::is_member_pointer<int (MyTypeF::*)>::value == true ); + EXAM_CHECK( std::tr1::is_member_pointer<int (MyTypeF::*)()>::value == true ); + + EXAM_CHECK( std::tr1::is_member_pointer<int>::value == false ); + EXAM_CHECK( std::tr1::is_member_pointer<int *>::value == false ); + EXAM_CHECK( std::tr1::is_member_pointer<int (*)()>::value == false ); + EXAM_CHECK( std::tr1::is_member_pointer<int (&)()>::value == false ); + EXAM_CHECK( std::tr1::is_member_pointer<int (void)>::value == false ); + + return EXAM_RESULT; +} + +int EXAM_IMPL(misc_test::type_traits_is_const) +{ + EXAM_CHECK( std::tr1::is_const<const int>::value == true ); + EXAM_CHECK( std::tr1::is_const<const volatile int>::value == true ); + // EXAM_CHECK( std::tr1::is_const<const int&>::value == true ); + EXAM_CHECK( std::tr1::is_const<int* const>::value == true ); + EXAM_CHECK( std::tr1::is_const<int* const volatile>::value == true ); + + EXAM_CHECK( std::tr1::is_const<const int*>::value == false ); + EXAM_CHECK( std::tr1::is_const<int>::value == false ); + EXAM_CHECK( std::tr1::is_const<volatile int>::value == false ); + + return EXAM_RESULT; +} + +int EXAM_IMPL(misc_test::type_traits_is_volatile) +{ + EXAM_CHECK( std::tr1::is_volatile<volatile int>::value == true ); + EXAM_CHECK( std::tr1::is_volatile<const volatile int>::value == true ); + // EXAM_CHECK( std::tr1::is_volatile<const int&>::value == true ); + EXAM_CHECK( std::tr1::is_volatile<int* volatile>::value == true ); + EXAM_CHECK( std::tr1::is_volatile<int* const volatile>::value == true ); + + EXAM_CHECK( std::tr1::is_volatile<volatile int*>::value == false ); + EXAM_CHECK( std::tr1::is_volatile<int>::value == false ); + EXAM_CHECK( std::tr1::is_volatile<const int>::value == false ); + + return EXAM_RESULT; +} + +struct N // neither trivial nor standard-layout +{ + int i; + int j; + + virtual ~N() + { } +}; + +struct T // trivial, but not standard-layout +{ + int i; + + private: + int j; +}; + +struct SL // standard-layout, but not trivial +{ + int i; + int j; + + ~SL() + { } +}; + +struct POD // both trivial and standard-layout, aka POD +{ + int i; + int j; +}; + +struct NT // standard-layout, but not trivial +{ + SL i; + int j; +}; + +int EXAM_IMPL(misc_test::type_traits_is_trivial) +{ + EXAM_CHECK( std::tr1::is_trivial<const int>::value == true ); + EXAM_CHECK( std::tr1::is_trivial<int *>::value == true ); + EXAM_CHECK( std::tr1::is_trivial<T>::value == true ); + EXAM_CHECK( std::tr1::is_trivial<POD>::value == true ); + + EXAM_CHECK( std::tr1::is_trivial<N>::value == false ); + EXAM_CHECK( std::tr1::is_trivial<SL>::value == false ); + EXAM_CHECK( std::tr1::is_trivial<NT>::value == false ); + + return EXAM_RESULT; +} + +int EXAM_IMPL(misc_test::type_traits_is_standard_layout) +{ + EXAM_CHECK( std::tr1::is_standard_layout<const int>::value == true ); + EXAM_CHECK( std::tr1::is_standard_layout<int *>::value == true ); + EXAM_CHECK( std::tr1::is_standard_layout<SL>::value == true ); + EXAM_CHECK( std::tr1::is_standard_layout<NT>::value == true ); + EXAM_CHECK( std::tr1::is_standard_layout<POD>::value == true ); + + EXAM_CHECK( std::tr1::is_standard_layout<N>::value == false ); + EXAM_CHECK( std::tr1::is_standard_layout<T>::value == false ); + + return EXAM_RESULT; +} + +int EXAM_IMPL(misc_test::type_traits_is_pod) +{ + EXAM_CHECK( std::tr1::is_pod<const int>::value == true ); + EXAM_CHECK( std::tr1::is_pod<int *>::value == true ); + EXAM_CHECK( std::tr1::is_pod<NT>::value == true ); + EXAM_CHECK( std::tr1::is_pod<POD>::value == true ); + + EXAM_CHECK( std::tr1::is_pod<SL>::value == false ); + EXAM_CHECK( std::tr1::is_pod<N>::value == false ); + EXAM_CHECK( std::tr1::is_pod<T>::value == false ); + + return EXAM_RESULT; +} + class empty { }; @@ -70,7 +532,7 @@ int k; }; -class not_empty2 +class empty1 { private: int f() const @@ -84,8 +546,8 @@ { return 0; } }; -class not_empty4 : - public not_empty2 +class empty2 : + public empty1 { }; @@ -98,11 +560,11 @@ { EXAM_CHECK( std::tr1::is_empty<empty>::value == true ); EXAM_CHECK( std::tr1::is_empty<not_empty1>::value == false ); - // EXAM_CHECK( std::tr1::is_empty<not_empty2>::value == false ); + EXAM_CHECK( std::tr1::is_empty<empty1>::value == true ); EXAM_CHECK( std::tr1::is_empty<not_empty3>::value == false ); EXAM_CHECK( std::tr1::is_empty<int>::value == false ); // EXAM_CHECK( std::tr1::is_empty<int (&)()>::value == false ); - // EXAM_CHECK( std::tr1::is_empty<not_empty4>::value == false ); + EXAM_CHECK( std::tr1::is_empty<empty2>::value == true ); EXAM_CHECK( std::tr1::is_empty<not_empty5>::value == false ); return EXAM_RESULT; Modified: trunk/complement/explore/lib/misc/ut/misc_test.h =================================================================== --- trunk/complement/explore/lib/misc/ut/misc_test.h 2008-02-27 14:18:00 UTC (rev 1819) +++ trunk/complement/explore/lib/misc/ut/misc_test.h 2008-02-27 14:18:59 UTC (rev 1820) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <07/07/16 21:01:43 ptr> +// -*- C++ -*- Time-stamp: <07/12/02 18:50:20 ptr> /* * Copyright (c) 2007 @@ -18,7 +18,38 @@ class misc_test { public: + // implementation int EXAM_DECL(type_traits_internals); + // [20.4.4.1] + int EXAM_DECL(type_traits_is_void); + int EXAM_DECL(type_traits_is_integral); + int EXAM_DECL(type_traits_is_floating_point); + int EXAM_DECL(type_traits_is_array); + int EXAM_DECL(type_traits_is_pointer); + int EXAM_DECL(type_traits_is_lvalue_reference); + // int EXAM_DECL(type_traits_is_rvalue_reference); + int EXAM_DECL(type_traits_is_member_object_pointer); + int EXAM_DECL(type_traits_is_member_function_pointer); + int EXAM_DECL(type_traits_is_enum); + int EXAM_DECL(type_traits_is_union); + int EXAM_DECL(type_traits_is_class); + int EXAM_DECL(type_traits_is_function); + + // [20.4.4.2] + int EXAM_DECL(type_traits_is_reference); + int EXAM_DECL(type_traits_is_arithmetic); + int EXAM_DECL(type_traits_is_fundamental); + int EXAM_DECL(type_traits_is_object); + int EXAM_DECL(type_traits_is_scalar); + int EXAM_DECL(type_traits_is_compound); + int EXAM_DECL(type_traits_is_member_pointer); + + // [20.4.4.3] + int EXAM_DECL(type_traits_is_const); + int EXAM_DECL(type_traits_is_volatile); + int EXAM_DECL(type_traits_is_trivial); + int EXAM_DECL(type_traits_is_standard_layout); + int EXAM_DECL(type_traits_is_pod); int EXAM_DECL(type_traits_is_empty); }; Modified: trunk/complement/explore/lib/misc/ut/misc_test_suite.cc =================================================================== --- trunk/complement/explore/lib/misc/ut/misc_test_suite.cc 2008-02-27 14:18:00 UTC (rev 1819) +++ trunk/complement/explore/lib/misc/ut/misc_test_suite.cc 2008-02-27 14:18:59 UTC (rev 1820) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <07/07/17 10:20:08 ptr> +// -*- C++ -*- Time-stamp: <07/12/02 18:57:27 ptr> /* * Copyright (c) 2007 @@ -18,10 +18,41 @@ exam::test_suite t( "libmisc? test" ); misc_test test; - exam::test_suite::test_case_type tc[3]; + exam::test_suite::test_case_type tc[10]; - t.add( &misc_test::type_traits_is_empty, test, "misc_test::type_traits_is_empty", - t.add( &misc_test::type_traits_internals, test, "misc_test::type_traits_internals" ) ); + tc[0] = t.add( &misc_test::type_traits_internals, test, "traits_internals" ); + t.add( &misc_test::type_traits_is_void, test, "is_void", tc[0] ); + tc[1] = t.add( &misc_test::type_traits_is_integral, test, "is_integral", tc[0] ); + tc[2] = t.add( &misc_test::type_traits_is_floating_point, test, "is_floating_point", tc[0] ); + t.add( &misc_test::type_traits_is_array, test, "is_array", tc[0] ); + t.add( &misc_test::type_traits_is_pointer, test, "is_pointer", tc[0] ); + t.add( &misc_test::type_traits_is_lvalue_reference, test, "is_lvalue_reference", tc[0] ); + // t.add( &misc_test::type_traits_is_rvalue_reference, test, "is_rvalue_reference", tc[0] ); + + t.add( &misc_test::type_traits_is_member_object_pointer, test, "is_member_object_pointer", tc[0] ); + t.add( &misc_test::type_traits_is_member_function_pointer, test, "is_member_function_pointer", tc[0] ); + + t.add( &misc_test::type_traits_is_enum, test, "is_enum", tc[0] ); + t.add( &misc_test::type_traits_is_function, test, "is_function", tc[0] ); + + // [20.4.4.2] + t.add( &misc_test::type_traits_is_reference, test, "is_reference", tc[0] ); + tc[3] = t.add( &misc_test::type_traits_is_arithmetic, test, "is_arithmetic", tc + 1, tc + 3 ); + t.add( &misc_test::type_traits_is_fundamental, test, "is_fundamental", tc[3] ); + + t.add( &misc_test::type_traits_is_object, test, "is_object", tc[0] ); + t.add( &misc_test::type_traits_is_scalar, test, "is_scalar", tc[0] ); + t.add( &misc_test::type_traits_is_compound, test, "is_compound", tc[0] ); + t.add( &misc_test::type_traits_is_member_pointer, test, "is_member_pointer", tc[0] ); + + // [20.4.4.3] + t.add( &misc_test::type_traits_is_const, test, "is_const", tc[0] ); + t.add( &misc_test::type_traits_is_volatile, test, "is_volatile", tc[0] ); + // t.add( &misc_test::type_traits_is_trivial, test, "is_trivial", tc[0] ); + // t.add( &misc_test::type_traits_is_standard_layout, test, "is_standard_layout", tc[0] ); + t.add( &misc_test::type_traits_is_pod, test, "is_pod", tc[0] ); + t.add( &misc_test::type_traits_is_empty, test, "is_empty", tc[0] ); + return t.girdle(); }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-02-27 14:18:34
|
Revision: 1819 http://complement.svn.sourceforge.net/complement/?rev=1819&view=rev Author: complement Date: 2008-02-27 06:18:00 -0800 (Wed, 27 Feb 2008) Log Message: ----------- is_[rl]value_reference added; is_object changed Modified Paths: -------------- trunk/complement/explore/include/misc/type_traits.h Modified: trunk/complement/explore/include/misc/type_traits.h =================================================================== --- trunk/complement/explore/include/misc/type_traits.h 2008-02-27 14:13:55 UTC (rev 1818) +++ trunk/complement/explore/include/misc/type_traits.h 2008-02-27 14:18:00 UTC (rev 1819) @@ -1,4 +1,4 @@ -// -*- C++ -*- Time-stamp: <07/11/24 00:28:34 ptr> +// -*- C++ -*- Time-stamp: <07/12/02 19:55:42 ptr> /* * Copyright (c) 2007 @@ -256,6 +256,26 @@ __CV_SPEC_1(is_pointer,_Tp *,true); template <class _Tp> +struct is_lvalue_reference : + public false_type +{ }; + +template <class _Tp> +struct is_lvalue_reference<_Tp&> : + public true_type +{ }; + +template <class _Tp> +struct is_rvalue_reference : + public false_type +{ }; + +// template <class _Tp> +// struct is_rvalue_reference<_Tp&&> : +// public true_type +// { }; + +template <class _Tp> struct is_reference : public false_type { }; @@ -374,8 +394,11 @@ template <class _Tp> struct is_object : - public integral_constant<bool, !(is_function<_Tp>::value || is_reference<_Tp>::value - || is_void<_Tp>::value)> + public integral_constant<bool, (is_arithmetic<_Tp>::value || + is_array<_Tp>::value || + is_pointer<_Tp>::value || + is_member_pointer<_Tp>::value || + detail::__is_union_or_class<_Tp>::value)> { }; template <class _Tp> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-02-27 14:13:58
|
Revision: 1818 http://complement.svn.sourceforge.net/complement/?rev=1818&view=rev Author: complement Date: 2008-02-27 06:13:55 -0800 (Wed, 27 Feb 2008) Log Message: ----------- gmake/lib/gcc.mak: 3.3 is normal compiler, just some builds was wrong---use common scheme for compiler's libraries; gmake/gcc.mak: option for 64-bit HP-UX at IA64; gmake/hp-ux/targetsys.mak: HP use .so for shared libs on intel-based 64-bits HP-UX; Modified Paths: -------------- trunk/complement/explore/Makefiles/ChangeLog trunk/complement/explore/Makefiles/gmake/gcc.mak trunk/complement/explore/Makefiles/gmake/hp-ux/targetsys.mak trunk/complement/explore/Makefiles/gmake/lib/gcc.mak Modified: trunk/complement/explore/Makefiles/ChangeLog =================================================================== --- trunk/complement/explore/Makefiles/ChangeLog 2008-02-26 14:39:44 UTC (rev 1817) +++ trunk/complement/explore/Makefiles/ChangeLog 2008-02-27 14:13:55 UTC (rev 1818) @@ -1,3 +1,14 @@ +2008-02-27 Petr Ovtchenkov <pt...@is...> + + * gmake/lib/gcc.mak: 3.3 is normal compiler, just some + builds was wrong---use common scheme for compiler's + libraries; + + * gmake/gcc.mak: option for 64-bit HP-UX at IA64; + + * gmake/hp-ux/targetsys.mak: HP use .so for shared libs + on intel-based 64-bits HP-UX; + 2008-02-26 Petr Ovtchenkov <pt...@is...> * gmake/gcc.mak: use more convenient option -dumpversion Modified: trunk/complement/explore/Makefiles/gmake/gcc.mak =================================================================== --- trunk/complement/explore/Makefiles/gmake/gcc.mak 2008-02-26 14:39:44 UTC (rev 1817) +++ trunk/complement/explore/Makefiles/gmake/gcc.mak 2008-02-27 14:13:55 UTC (rev 1818) @@ -1,4 +1,4 @@ -# Time-stamp: <08/02/26 13:46:36 yeti> +# Time-stamp: <08/02/26 13:46:36 ptr> # # Copyright (c) 1997-1999, 2002, 2003, 2005-2008 # Petr Ovtchenkov @@ -133,6 +133,10 @@ endif ifeq ($(OSNAME),hp-ux) +ifneq ($(M_ARCH),ia64) +release-static : OPT += -fno-reorder-blocks +release-shared : OPT += -fno-reorder-blocks +endif CCFLAGS = -pthread $(OPT) CFLAGS = -pthread $(OPT) # CXXFLAGS = -pthread -nostdinc++ -fexceptions $(OPT) Modified: trunk/complement/explore/Makefiles/gmake/hp-ux/targetsys.mak =================================================================== --- trunk/complement/explore/Makefiles/gmake/hp-ux/targetsys.mak 2008-02-26 14:39:44 UTC (rev 1817) +++ trunk/complement/explore/Makefiles/gmake/hp-ux/targetsys.mak 2008-02-27 14:13:55 UTC (rev 1818) @@ -1,4 +1,4 @@ -# Time-stamp: <07/05/31 00:48:27 ptr> +# Time-stamp: <08/01/29 09:44:51 ptr> # # Copyright (c) 1997-1999, 2002, 2003, 2005-2007 # Petr Ovtchenkov @@ -9,7 +9,11 @@ # Licensed under the Academic Free License version 3.0 # +ifeq ($(M_ARCH),ia64) +SO := so +else SO := sl +endif ARCH := a AR := ar Modified: trunk/complement/explore/Makefiles/gmake/lib/gcc.mak =================================================================== --- trunk/complement/explore/Makefiles/gmake/lib/gcc.mak 2008-02-26 14:39:44 UTC (rev 1817) +++ trunk/complement/explore/Makefiles/gmake/lib/gcc.mak 2008-02-27 14:13:55 UTC (rev 1818) @@ -30,7 +30,7 @@ endif ifeq ($(CXX_VERSION_MAJOR),3) -# gcc before 3.4 (i.e. 3.0.x, 3.1.x, 3.2.x) has buggy libsupc++, so we should link with libstdc++ to avoid one +# gcc before 3.3 (i.e. 3.0.x, 3.1.x, 3.2.x) has buggy libsupc++, so we should link with libstdc++ to avoid one ifeq ($(CXX_VERSION_MINOR),0) NOT_USE_NOSTDLIB := 1 endif @@ -40,10 +40,7 @@ ifeq ($(CXX_VERSION_MINOR),2) NOT_USE_NOSTDLIB := 1 endif -ifeq ($(CXX_VERSION_MINOR),3) -NOT_USE_NOSTDLIB := 1 endif -endif endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-02-26 14:39:48
|
Revision: 1817 http://complement.svn.sourceforge.net/complement/?rev=1817&view=rev Author: complement Date: 2008-02-26 06:39:44 -0800 (Tue, 26 Feb 2008) Log Message: ----------- core implementation of JTC1/SC22/WG21 working draft, suggested as replacement for xmt Modified Paths: -------------- branches/wg21-thread/include/mt/mutex branches/wg21-thread/include/mt/system_error branches/wg21-thread/include/mt/thread branches/wg21-thread/lib/mt/ChangeLog branches/wg21-thread/lib/mt/Makefile.inc branches/wg21-thread/lib/mt/thread.cc branches/wg21-thread/lib/mt/ut/Makefile.inc branches/wg21-thread/lib/mt/ut/mt_test_suite.cc Added Paths: ----------- branches/wg21-thread/include/mt/condition_variable branches/wg21-thread/include/mt/date_time branches/wg21-thread/lib/mt/date_time.cc branches/wg21-thread/lib/mt/ut/mt_test_wg21.cc branches/wg21-thread/lib/mt/ut/mt_test_wg21.h Property Changed: ---------------- branches/wg21-thread/ branches/wg21-thread/include/ branches/wg21-thread/lib/ Property changes on: branches/wg21-thread ___________________________________________________________________ Name: svn:externals + Makefiles https://complement.svn.sourceforge.net/svnroot/complement/trunk/complement/explore/Makefiles Property changes on: branches/wg21-thread/include ___________________________________________________________________ Name: svn:externals + config https://complement.svn.sourceforge.net/svnroot/complement/trunk/complement/explore/include/config exam https://complement.svn.sourceforge.net/svnroot/complement/trunk/complement/explore/include/exam misc https://complement.svn.sourceforge.net/svnroot/complement/trunk/complement/explore/include/misc Copied: branches/wg21-thread/include/mt/condition_variable (from rev 1813, branches/wg21-thread/include/mt/xmt.h) =================================================================== --- branches/wg21-thread/include/mt/condition_variable (rev 0) +++ branches/wg21-thread/include/mt/condition_variable 2008-02-26 14:39:44 UTC (rev 1817) @@ -0,0 +1,773 @@ +// -*- C++ -*- Time-stamp: <08/02/25 13:09:15 ptr> + +/* + * Copyright (c) 1997-1999, 2002-2008 + * Petr Ovtchenkov + * + * Portion Copyright (c) 1999-2001 + * Parallel Graphics Ltd. + * + * Licensed under the Academic Free License version 3.0 + * + * Derived from original <mt/xmt.h> of 'complement' project + * [http://complement.sourceforge.net] + * to make it close to JTC1/SC22/WG21 working draft + * [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2497.html] + */ + +#ifndef __MT_CONDITION_VARIABLE +#define __MT_CONDITION_VARIABLE + +#ifndef __config_feature_h +#include <config/feature.h> +#endif + +#include <mt/date_time> +#include <mt/mutex> + +namespace std { + +namespace tr2 { + +template <bool SCOPE> +class __condition_variable +{ + public: + __condition_variable() + { +#ifdef __FIT_WIN32THREADS + _cond = CreateEvent( 0, TRUE, TRUE, 0 ); +#endif +#ifdef __FIT_PTHREADS + if ( SCOPE ) { + pthread_condattr_t attr; + pthread_condattr_init( &attr ); + pthread_condattr_setpshared( &attr, PTHREAD_PROCESS_SHARED ); + pthread_cond_init( &_cond, &attr ); + pthread_condattr_destroy( &attr ); + } else { + pthread_cond_init( &_cond, 0 ); + } +#endif + } + + ~__condition_variable() + { +#ifdef __FIT_WIN32THREADS + CloseHandle( _cond ); +#endif +#ifdef __FIT_PTHREADS + pthread_cond_destroy( &_cond ); +#endif + } + +#ifdef __FIT_PTHREADS + typedef pthread_cond_t* native_handle_type; +#endif +#ifdef __FIT_WIN32THREADS + typedef HANDLE native_handle_type; +#endif + + void notify_one() + { +#ifdef __FIT_WIN32THREADS + SetEvent( _cond ); +#endif +#ifdef __FIT_PTHREADS + pthread_cond_signal( &_cond ); +#endif + } + + void notify_all() + { +#ifdef __FIT_PTHREADS + pthread_cond_broadcast( &_cond ); +#endif + } + + void wait( unique_lock<__mutex<false,SCOPE> >& lock ) + { +#ifdef __FIT_WIN32THREADS + ResetEvent( _cond ); + lock.unlock(); + if ( WaitForSingleObject( _cond, -1 ) == WAIT_FAILED ) { + lock.lock(); + // throw system_error + } + lock.lock(); +#endif +#ifdef __FIT_PTHREADS + int ret = pthread_cond_wait( &_cond, &lock.m->_M_lock ); + if ( ret ) { + lock.lock(); + // throw system_error + } +#endif + } + + template <class Predicate> + void wait( unique_lock<__mutex<false,SCOPE> >& lock, Predicate pred ) + { + while ( !pred() ) { + wait( lock ); + } + } + + bool timed_wait( unique_lock<__mutex<false,SCOPE> >& lock, const system_time& abs_time ) + { +#ifdef __FIT_PTHREADS + ::timespec t; + t.tv_sec = abs_time.seconds_since_epoch(); + t.tv_nsec = static_cast<long>( abs_time.nanoseconds_since_epoch().count() % nanoseconds::ticks_per_second ); + int ret = pthread_cond_timedwait( &_cond, &lock.m->_M_lock, &t ); + if ( ret != 0 ) { + if ( ret == ETIMEDOUT ) { + return false; + } + // throw system_error + } +#endif + return true; + } + + template <class Duration> + bool timed_wait( unique_lock<__mutex<false,SCOPE> >& lock, const Duration& rel_time ) + { +#ifdef __FIT_PTHREADS + return timed_wait( lock, get_system_time() + rel_time ); +#endif + } + + template <class Predicate> + bool timed_wait( unique_lock<__mutex<false,SCOPE> >& lock, const system_time& abs_time, Predicate pred ) + { + while ( !pred() ) { + if ( !timed_wait( lock, abs_time ) ) { + return pred(); + } + } + return true; + } + + template <class Duration, class Predicate> + bool timed_wait( unique_lock<__mutex<false,SCOPE> >& lock, const Duration& rel_time, Predicate pred ) + { +#ifdef __FIT_PTHREADS + return timed_wait( lock, get_system_time() + rel_time, pred ); +#endif + } + + native_handle_type native_handle() + { +#ifdef __FIT_PTHREADS + return &_cond; +#endif +#ifdef __FIT_WIN32THREADS + return _cond; +#endif + } + + protected: +#ifdef __FIT_PTHREADS + pthread_cond_t _cond; +#endif +#ifdef __FIT_WIN32THREADS + HANDLE _cond; +#endif + + private: + __condition_variable( const __condition_variable& ) + { } +}; + +typedef __condition_variable<false> condition_variable; +typedef __condition_variable<true> condition_variable_ip; + +template <bool SCOPE> +class __condition_variable_any +{ + public: + __condition_variable_any() + { +#ifdef __FIT_WIN32THREADS + _cond = CreateEvent( 0, TRUE, TRUE, 0 ); +#endif +#ifdef __FIT_PTHREADS + if ( SCOPE ) { + pthread_condattr_t attr; + pthread_condattr_init( &attr ); + pthread_condattr_setpshared( &attr, PTHREAD_PROCESS_SHARED ); + pthread_cond_init( &_cond, &attr ); + pthread_condattr_destroy( &attr ); + } else { + pthread_cond_init( &_cond, 0 ); + } +#endif + } + + ~__condition_variable_any() + { +#ifdef __FIT_WIN32THREADS + CloseHandle( _cond ); +#endif +#ifdef __FIT_PTHREADS + pthread_cond_destroy( &_cond ); +#endif + } + +#ifdef __FIT_PTHREADS + typedef pthread_cond_t* native_handle_type; +#endif +#ifdef __FIT_WIN32THREADS + typedef HANDLE native_handle_type; +#endif + + void notify_one() + { +#ifdef __FIT_WIN32THREADS + SetEvent( _cond ); +#endif +#ifdef __FIT_PTHREADS + pthread_cond_signal( &_cond ); +#endif + } + + void notify_all() + { +#ifdef __FIT_PTHREADS + pthread_cond_broadcast( &_cond ); +#endif + } + + template <class Lock> + void wait( Lock& lock ) + { +#ifdef __FIT_WIN32THREADS + ResetEvent( _cond ); + lock.unlock(); + if ( WaitForSingleObject( _cond, -1 ) == WAIT_FAILED ) { + lock.lock(); + // throw system_error + } + lock.lock(); +#endif +#ifdef __FIT_PTHREADS + int ret = pthread_cond_wait( &_cond, lock.native_handle() ); + if ( ret ) { + lock.lock(); + // throw system_error + } +#endif + } + + template <class Lock, class Predicate> + void wait( Lock& lock, Predicate pred ) + { + while ( !pred() ) { + wait( lock ); + } + } + + template <class Lock> + bool timed_wait( Lock& lock, const system_time& abs_time ) + { +#ifdef __FIT_PTHREADS + ::timespec t; + t.tv_sec = abs_time.seconds_since_epoch(); + t.tv_nsec = static_cast<long>( abs_time.nanoseconds_since_epoch().count() % nanoseconds::ticks_per_second ); + int ret = pthread_cond_timedwait( &_cond, lock.native_handle(), &t ); + if ( ret != 0 ) { + if ( ret == ETIMEDOUT ) { + return false; + } + // throw system_error + } +#endif +#ifdef __FIT_WIN32THREADS + static const std::tr2::nanoseconds::tick_type _th = std::tr2::nanoseconds::ticks_per_second / std::tr2::milliseconds::ticks_per_second; + ResetEvent( _cond ); + lock.unlock(); + int ret = WaitForSingleObject( _cond, (abs_time - get_system_time()).count() / _th ); + lock.lock(); + if ( ret == WAIT_FAILED ) { + // throw system_error + } + if ( ret == WAIT_TIMEOUT ) { + SetEvent( _cond ); + return _val; + } +#endif + + return true; + } + + template <class Lock, class Duration> + bool timed_wait( Lock& lock, const Duration& rel_time ) + { +#ifdef __FIT_PTHREADS + return timed_wait( lock, get_system_time() + rel_time ); +#endif +#ifdef __FIT_WIN32THREADS + static const std::tr2::nanoseconds::tick_type _th = std::tr2::nanoseconds::ticks_per_second / Duration::ticks_per_second; + + ResetEvent( _cond ); + lock.unlock(); + int ret = WaitForSingleObject( _cond, rel_time.count() / _th ); + lock.lock(); + if ( ret == WAIT_FAILED ) { + // throw system_error + } + if ( ret == WAIT_TIMEOUT ) { + SetEvent( _cond ); + return _val; + } + + return true; +#endif + } + + template <class Lock, class Predicate> + bool timed_wait( Lock& lock, const system_time& abs_time, Predicate pred ) + { + while ( !pred() ) { + if ( !timed_wait( lock, abs_time ) ) { + return pred(); + } + } + return true; + } + + template <class Lock, class Duration, class Predicate> + bool timed_wait( Lock& lock, const Duration& rel_time, Predicate pred ) + { +#ifdef __FIT_PTHREADS + return timed_wait( lock, get_system_time() + rel_time, pred ); +#endif + } + + native_handle_type native_handle() + { +#ifdef __FIT_PTHREADS + return &_cond; +#endif +#ifdef __FIT_WIN32THREADS + return _cond; +#endif + } + + protected: +#ifdef __FIT_PTHREADS + pthread_cond_t _cond; +#endif +#ifdef __FIT_WIN32THREADS + HANDLE _cond; +#endif + + private: + __condition_variable_any( const __condition_variable_any& ) + { } +}; + +typedef __condition_variable_any<false> condition_variable_any; +typedef __condition_variable_any<true> condition_variable_any_ip; + +template <bool SCOPE> +class __condition_event +{ + public: + __condition_event() : + _val( false ) + { +#ifdef __FIT_WIN32THREADS + _cond = CreateEvent( 0, TRUE, TRUE, 0 ); +#endif +#ifdef __FIT_PTHREADS + if ( SCOPE ) { + pthread_condattr_t attr; + pthread_condattr_init( &attr ); + pthread_condattr_setpshared( &attr, PTHREAD_PROCESS_SHARED ); + pthread_cond_init( &_cond, &attr ); + pthread_condattr_destroy( &attr ); + } else { + pthread_cond_init( &_cond, 0 ); + } +#endif + } + + ~__condition_event() + { +#ifdef __FIT_WIN32THREADS + CloseHandle( _cond ); +#endif +#ifdef __FIT_PTHREADS + pthread_cond_destroy( &_cond ); +#endif + } + + void notify_one() + { + { + unique_lock<__mutex<false,SCOPE> > lk( _lock ); + + if ( _val ) { + return; + } + + _val = true; + } + +#ifdef __FIT_WIN32THREADS + SetEvent( _cond ); +#endif +#ifdef __FIT_PTHREADS + if ( pthread_cond_signal( &_cond ) ) { + // throw system_error + } +#endif + } + + void notify_all() + { + { + unique_lock<__mutex<false,SCOPE> > lk( _lock ); + + if ( _val ) { + return; + } + + _val = true; + } + +#ifdef __FIT_WIN32THREADS + if ( SetEvent( _cond ) == FALSE ) { + // throw system_error + } +#endif +#ifdef __FIT_PTHREADS + if ( pthread_cond_broadcast( &_cond ) ) { + // throw system_error + } +#endif + } + + void reset() + { + unique_lock<__mutex<false,SCOPE> > lk( _lock ); + _val = false; + } + + void wait() + { + unique_lock<__mutex<false,SCOPE> > lk( _lock ); + +#ifdef __FIT_WIN32THREADS + ResetEvent( _cond ); + lk.unlock(); + if ( WaitForSingleObject( _cond, -1 ) == WAIT_FAILED ) { + lk.lock(); + // throw system_error + } + lk.lock(); +#endif +#ifdef __FIT_PTHREADS + int ret; + while ( !_val ) { + ret = pthread_cond_wait( &_cond, &_lock._M_lock ); + if ( ret ) { + // throw system_error + } + } +#endif + } + + bool timed_wait(const system_time& abs_time ) + { + unique_lock<__mutex<false,SCOPE> > lk( _lock ); + +#ifdef __FIT_PTHREADS + ::timespec t; + t.tv_sec = abs_time.seconds_since_epoch(); + t.tv_nsec = static_cast<long>( abs_time.nanoseconds_since_epoch().count() % nanoseconds::ticks_per_second ); + while ( !_val ) { + int ret = pthread_cond_timedwait( &_cond, _lock.native_handle(), &t ); + if ( ret != 0 ) { + if ( ret == ETIMEDOUT ) { + return _val; + } + // throw system_error + } + } +#endif + +#ifdef __FIT_WIN32THREADS + static const std::tr2::nanoseconds::tick_type _th = std::tr2::nanoseconds::ticks_per_second / std::tr2::milliseconds::ticks_per_second; + ResetEvent( _cond ); + lk.unlock(); + int ret = WaitForSingleObject( _cond, (abs_time - get_system_time()).count() / _th ); + lk.lock(); + if ( ret == WAIT_FAILED ) { + // throw system_error + } + if ( ret == WAIT_TIMEOUT ) { + SetEvent( _cond ); + return _val; + } +#endif + + return true; + } + + template <class Duration> + bool timed_wait( const Duration& rel_time ) + { +#ifdef __FIT_PTHREADS + return timed_wait( get_system_time() + rel_time ); +#endif +#ifdef __FIT_WIN32THREADS + static const std::tr2::nanoseconds::tick_type _th = std::tr2::nanoseconds::ticks_per_second / Duration::ticks_per_second; + + unique_lock<__mutex<false,SCOPE> > lk( _lock ); + + ResetEvent( _cond ); + lk.unlock(); + int ret = WaitForSingleObject( _cond, rel_time.count() / _th ); + lk.lock(); + if ( ret == WAIT_FAILED ) { + // throw system_error + } + if ( ret == WAIT_TIMEOUT ) { + SetEvent( _cond ); + return _val; + } + + return true; +#endif + } + + protected: +#ifdef __FIT_WIN32THREADS + HANDLE _cond; +#endif +#ifdef __FIT_PTHREADS + pthread_cond_t _cond; +#endif + __mutex<false,SCOPE> _lock; + bool _val; + + private: + __condition_event( const __condition_event& ) + { } +}; + +typedef __condition_event<false> condition_event; +typedef __condition_event<true> condition_event_ip; + +template <bool SCOPE> +class __semaphore +{ + public: + __semaphore( int cnt = 1 ) + { +#ifdef __FIT_WIN32THREADS + _sem = CreateSemaphore( NULL, cnt, INT_MAX, 0 ); // check! + _cnt = cnt; +#endif +#ifdef __FIT_PTHREADS + sem_init( &_sem, SCOPE ? 1 : 0, cnt ); +#endif + } + + ~__semaphore() + { +#ifdef __FIT_WIN32THREADS + CloseHandle( _sem ); +#endif +#ifdef __FIT__PTHREADS + sem_destroy( &_sem ); +#endif + } + + void wait() + { +#ifdef __FIT_WIN32THREADS + --_cnt; + if ( WaitForSingleObject( _sem, -1 ) == WAIT_FAILED ) { + ++_cnt; + // throw system_error + } +#endif +#ifdef __FIT_PTHREADS + int ret = sem_wait( &_sem ); + if ( ret != 0 ) { + // throw system_error + } +#endif + } + + bool try_wait() + { +#ifdef __FIT_WIN32THREADS + return _cnt > 0 ? (--_cnt, this->wait()) : -1; +#endif +#ifdef __FIT_PTHREADS + int ret = sem_trywait( &_sem ); + if ( ret != 0 ) { + if ( ret == EBUSY ) { + return false; + } + // throw system_error + } + return true; +#endif + } + + bool timed_wait(const system_time& abs_time ) + { +#ifdef __FIT_PTHREADS + ::timespec t; + t.tv_sec = abs_time.seconds_since_epoch(); + t.tv_nsec = static_cast<long>( abs_time.nanoseconds_since_epoch().count() % nanoseconds::ticks_per_second ); +# if !(defined(__FreeBSD__) || defined(__OpenBSD__)) + int ret = sem_timedwait( &_sem, &t ); + if ( ret != 0 ) { + if ( ret == ETIMEDOUT ) { + return false; + } + // throw system_error + } +# endif +#endif +#ifdef __FIT_WIN32THREADS + static const std::tr2::nanoseconds::tick_type _th = std::tr2::nanoseconds::ticks_per_second / std::tr2::milliseconds::ticks_per_second; + int ret = WaitForSingleObject( _sem, (abs_time - get_system_time()).count() / _th ); + if ( ret == WAIT_FAILED ) { + // throw system_error + } + if ( ret == WAIT_TIMEOUT ) { + return false; + } +#endif + return true; + } + + template <class Duration> + bool timed_wait( const Duration& rel_time ) + { +#ifdef __FIT_PTHREADS + return timed_wait( get_system_time() + rel_time ); +#endif +#ifdef __FIT_WIN32THREADS + static const std::tr2::nanoseconds::tick_type _th = std::tr2::nanoseconds::ticks_per_second / Duration::ticks_per_second; + + int ret = WaitForSingleObject( _sem, rel_time.count() / _th ); + + if ( ret == WAIT_OBJECT_0 ) { + return true; + } + + if ( ret == WAIT_FAILED ) { + // throw system_error + } + if ( ret == WAIT_TIMEOUT ) { + return false; + } + + return true; +#endif + } + + + void notify_one() + { +#ifdef __FIT_WIN32THREADS + int ret = ReleaseSemaphore( _sem, 1, &_cnt ) != 0 ? (++_cnt, 0) : -1; + if ( ret != 0 ) { + // throw system_error + } +#endif +#ifdef __FIT_PTHREADS + int ret = sem_post( &_sem ); + if ( ret != 0 ) { + // throw system_error + } +#endif + } + + int value() + { +#ifdef __FIT_WIN32THREADS + return static_cast<int>(_cnt); +#endif +#ifdef __FIT_PTHREADS + int v; + int e = sem_getvalue( &_sem, &v ); + if ( e != 0 ) { + // throw system_error + } + + return v; +#endif + } + + protected: +#ifdef __FIT_WIN32THREADS + HANDLE _sem; + long _cnt; +#endif +#ifdef __FIT_PTHREADS + sem_t _sem; +#endif + private: + __semaphore( const __semaphore& ) + { } +}; + +typedef __semaphore<false> semaphore; +typedef __semaphore<true> semaphore_ip; + +template <bool SCOPE> +class __barrier +{ + public: + __barrier( unsigned cnt = 2 ) + { +#ifdef _PTHREADS + pthread_barrierattr_t attr; + pthread_barrierattr_init( &attr ); + pthread_barrierattr_setpshared( &attr, SCOPE ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE ); + pthread_barrier_init( &_barr, &attr, cnt ); + pthread_barrierattr_destroy( &attr ); +#endif + } + + ~__barrier() + { +#ifdef __FIT_PTHREADS + pthread_barrier_destroy( &_barr ); +#endif + } + + void wait() + { +#ifdef __FIT_PTHREADS + int ret = pthread_barrier_wait( &_barr ); + if ( ret != 0 ) { + // throw system_error + } +#endif + } + + private: +#ifdef __FIT_PTHREADS + pthread_barrier_t _barr; +#endif +}; + +typedef __barrier<false> barrier; +typedef __barrier<false> barrier_ip; + +} // namespace tr2 + +} // namespace std + +#endif // __MT_CONDITION_VARIABLE Copied: branches/wg21-thread/include/mt/date_time (from rev 1813, branches/wg21-thread/include/mt/time.h) =================================================================== --- branches/wg21-thread/include/mt/date_time (rev 0) +++ branches/wg21-thread/include/mt/date_time 2008-02-26 14:39:44 UTC (rev 1817) @@ -0,0 +1,1116 @@ +// -*- C++ -*- Time-stamp: <08/02/25 13:08:13 ptr> + +/* + * Copyright (c) 2002, 2006-2008 + * Petr Ovtchenkov + * + * Licensed under the Academic Free License version 3.0 + * + * Derived from original <mt/time.h> of 'complement' project + * [http://complement.sourceforge.net] + * to make it close to JTC1/SC22/WG21 working draft + * [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2497.html] + */ + +#ifndef __MT_DATE_TIME +#define __MT_DATE_TIME + +#ifndef __config_feature_h +#include <config/feature.h> +#endif + +#include <string> +#include <misc/type_traits.h> +#include <functional> + +namespace std { + +namespace tr2 { + +class system_time; +class nanoseconds; +class microseconds; +class milliseconds; +class seconds; +class minutes; +class hours; + +namespace detail { + +typedef long long signed_tick_type; // int64_t +typedef unsigned long long unsigned_tick_type; // uint64_t + +template <class _Tp1, class _Tp2> +struct __is_more_precise : + public std::tr1::false_type +{ + typedef _Tp2 finest_type; +}; + +template <class _Tp> +struct __is_more_precise<std::tr2::nanoseconds,_Tp> : + public std::tr1::true_type +{ + typedef std::tr2::nanoseconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::microseconds,milliseconds> : + public std::tr1::true_type +{ + typedef std::tr2::microseconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::microseconds,seconds> : + public std::tr1::true_type +{ + typedef std::tr2::microseconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::microseconds,minutes> : + public std::tr1::true_type +{ + typedef std::tr2::microseconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::microseconds,hours> : + public std::tr1::true_type +{ + typedef std::tr2::microseconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::milliseconds,seconds> : + public std::tr1::true_type +{ + typedef std::tr2::milliseconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::milliseconds,minutes> : + public std::tr1::true_type +{ + typedef std::tr2::milliseconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::milliseconds,hours> : + public std::tr1::true_type +{ + typedef std::tr2::milliseconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::seconds,minutes> : + public std::tr1::true_type +{ + typedef std::tr2::seconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::seconds,hours> : + public std::tr1::true_type +{ + typedef std::tr2::seconds finest_type; +}; + +template <> +struct __is_more_precise<std::tr2::minutes,hours> : + public std::tr1::true_type +{ + typedef std::tr2::minutes finest_type; +}; + +template <class LhsDuration, class RhsDuration, class Op, bool Pre> +struct __op_aux +{ + bool operator()( const LhsDuration& lhs, const RhsDuration& rhs ) const + { return Op()( static_cast<RhsDuration>(lhs).count(), rhs.count()); } +}; + +template <class LhsDuration, class RhsDuration, class Op> +struct __op_aux<LhsDuration,RhsDuration,Op,true> +{ + bool operator()( const LhsDuration& lhs, const RhsDuration& rhs ) const + { return Op()(lhs.count(), static_cast<LhsDuration>(rhs).count() ); } +}; + +template <class LhsDuration, class RhsDuration, class Op, bool Pre> +struct __op_aux2 +{ + signed_tick_type operator()( const LhsDuration& lhs, const RhsDuration& rhs ) const + { return Op()( static_cast<RhsDuration>(lhs).count(), rhs.count()); } +}; + +template <class LhsDuration, class RhsDuration, class Op> +struct __op_aux2<LhsDuration,RhsDuration,Op,true> +{ + signed_tick_type operator()( const LhsDuration& lhs, const RhsDuration& rhs ) const + { return Op()(lhs.count(), static_cast<LhsDuration>(rhs).count() ); } +}; + +struct add : + public std::binary_function<signed_tick_type,signed_tick_type,signed_tick_type> +{ + signed_tick_type operator()(signed_tick_type __x, signed_tick_type __y) const + { return __x + __y; } +}; + +struct sub : + public std::binary_function<signed_tick_type,signed_tick_type,signed_tick_type> +{ + signed_tick_type operator()(signed_tick_type __x, signed_tick_type __y) const + { return __x - __y; } +}; + +} // namespace detail + +class nanoseconds +{ + public: + typedef std::tr2::detail::signed_tick_type tick_type; + + static const tick_type ticks_per_second; + static const tick_type seconds_per_tick; + static const bool is_subsecond; + + nanoseconds( long long ns = 0LL ) : + tv( ns ) + { } + + tick_type count() const + { return tv; } + + template <typename Duration> + nanoseconds& operator -=( const Duration& d ) + { + static const tick_type factor = Duration::is_subsecond ? nanoseconds::ticks_per_second / Duration::ticks_per_second : nanoseconds::ticks_per_second * Duration::seconds_per_tick; + + tv -= d.tv * factor; + return *this; + } + + template <typename Duration> + nanoseconds& operator +=( const Duration& d ) + { + static const tick_type factor = Duration::is_subsecond ? nanoseconds::ticks_per_second / Duration::ticks_per_second : nanoseconds::ticks_per_second * Duration::seconds_per_tick; + + tv += d.tv * factor; + return *this; + } + + nanoseconds& operator *=( long v ) + { + tv *= v; + return *this; + } + + nanoseconds& operator /=( long v ) + { + tv /= v; + return *this; + } + + nanoseconds operator -() const + { return nanoseconds( -tv ); } + + bool operator ==( const nanoseconds& r ) const + { return tv == r.tv; } + + template <class Duration> + bool operator ==( const Duration& r ) const + { return tv == static_cast<nanoseconds>(r).count(); } + + bool operator !=( const nanoseconds& r ) const + { return tv != r.tv; } + + template <class Duration> + bool operator !=( const Duration& r ) const + { return tv != static_cast<nanoseconds>(r).count(); } + + bool operator <( const nanoseconds& r ) const + { return tv < r.tv; } + + template <class Duration> + bool operator <( const Duration& r ) const + { return tv < static_cast<nanoseconds>(r).count(); } + + bool operator <=( const nanoseconds& r ) const + { return tv <= r.tv; } + + template <class Duration> + bool operator <=( const Duration& r ) const + { return tv <= static_cast<nanoseconds>(r).count(); } + + bool operator >( const nanoseconds& r ) const + { return tv > r.tv; } + + template <class Duration> + bool operator >( const Duration& r ) const + { return tv > static_cast<nanoseconds>(r).count(); } + + bool operator >=( const nanoseconds& r ) const + { return tv >= r.tv; } + + template <class Duration> + bool operator >=( const Duration& r ) const + { return tv >= static_cast<nanoseconds>(r).count(); } + + nanoseconds operator +( const nanoseconds& r ) const + { return nanoseconds( tv + r.tv ); } + + system_time operator +( const system_time& r ) const; + + template <class Duration> + nanoseconds operator +(const Duration& r) const + { return nanoseconds( tv + static_cast<nanoseconds>(r).count() ); } + + nanoseconds operator -( const nanoseconds& r ) const + { return nanoseconds( tv - r.tv ); } + + template <class Duration> + nanoseconds operator -(const Duration& r) const + { return nanoseconds( tv - static_cast<nanoseconds>(r).count() ); } + + nanoseconds operator *( long r ) const + { return nanoseconds( tv * r ); } + + nanoseconds operator /( long r ) const + { return nanoseconds( tv / r ); } + + private: + tick_type tv; + + friend class microseconds; + friend class milliseconds; + friend class seconds; + friend class minutes; + friend class hours; +}; + +class microseconds +{ + public: + typedef std::tr2::detail::signed_tick_type tick_type; + + static const tick_type ticks_per_second; + static const tick_type seconds_per_tick; + static const bool is_subsecond; + + microseconds( long long us = 0LL ) : + tv( us ) + { } + + tick_type count() const + { return tv; } + + template <typename RhsDuration> + microseconds& operator -=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv -= d.tv * factor / 1000LL; + return *this; + } + + + template <typename RhsDuration> + microseconds& operator +=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv += d.tv * factor / 1000LL; + return *this; + } + + + microseconds& operator *=( long v ) + { + tv *= v; + return *this; + } + + microseconds& operator /=( long v ) + { + tv /= v; + return *this; + } + + microseconds operator -() const + { return microseconds( -tv ); } + + operator nanoseconds() const + { return nanoseconds(tv * 1000LL); } + + bool operator ==( const microseconds& r ) const + { return tv == r.tv; } + + template <class Duration> + bool operator ==( const Duration& r ) const + { return std::tr2::detail::__op_aux<microseconds,Duration,std::equal_to<tick_type>,std::tr2::detail::__is_more_precise<microseconds,Duration>::value>()( *this, r ); } + + bool operator !=( const microseconds& r ) const + { return tv != r.tv; } + + template <class Duration> + bool operator !=( const Duration& r ) const + { return std::tr2::detail::__op_aux<microseconds,Duration,std::not_equal_to<tick_type>,std::tr2::detail::__is_more_precise<microseconds,Duration>::value>()( *this, r ); } + + bool operator <( const microseconds& r ) const + { return tv < r.tv; } + + template <class Duration> + bool operator <( const Duration& r ) const + { return std::tr2::detail::__op_aux<microseconds,Duration,std::less<tick_type>,std::tr2::detail::__is_more_precise<microseconds,Duration>::value>()( *this, r ); } + + bool operator <=( const microseconds& r ) const + { return tv <= r.tv; } + + template <class Duration> + bool operator <=( const Duration& r ) const + { return std::tr2::detail::__op_aux<microseconds,Duration,std::less_equal<tick_type>,std::tr2::detail::__is_more_precise<microseconds,Duration>::value>()( *this, r ); } + + bool operator >( const microseconds& r ) const + { return tv > r.tv; } + + template <class Duration> + bool operator >( const Duration& r ) const + { return std::tr2::detail::__op_aux<microseconds,Duration,std::greater<tick_type>,std::tr2::detail::__is_more_precise<microseconds,Duration>::value>()( *this, r ); } + + bool operator >=( const microseconds& r ) const + { return tv >= r.tv; } + + template <class Duration> + bool operator >=( const Duration& r ) const + { return std::tr2::detail::__op_aux<microseconds,Duration,std::greater_equal<tick_type>,std::tr2::detail::__is_more_precise<microseconds,Duration>::value>()( *this, r ); } + + microseconds operator +( const microseconds& r ) const + { return microseconds( tv + r.tv ); } + + system_time operator +( const system_time& r ) const; + + template <class Duration> + typename std::tr2::detail::__is_more_precise<microseconds,Duration>::finest_type operator +(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<microseconds,Duration>::finest_type( + std::tr2::detail::__op_aux2<microseconds,Duration,std::tr2::detail::add,std::tr2::detail::__is_more_precise<microseconds,Duration>::value>()( *this, r ) ); + } + + microseconds operator -( const microseconds& r ) const + { return microseconds( tv - r.tv ); } + + template <class Duration> + typename std::tr2::detail::__is_more_precise<microseconds,Duration>::finest_type operator -(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<microseconds,Duration>::finest_type( + std::tr2::detail::__op_aux2<microseconds,Duration,std::tr2::detail::sub,std::tr2::detail::__is_more_precise<microseconds,Duration>::value>()( *this, r ) ); + } + + microseconds operator *( long r ) const + { return microseconds( tv * r ); } + + microseconds operator /( long r ) const + { return microseconds( tv / r ); } + + private: + tick_type tv; + + friend class nanoseconds; + friend class milliseconds; + friend class seconds; + friend class minutes; + friend class hours; +}; + +class milliseconds +{ + public: + typedef std::tr2::detail::signed_tick_type tick_type; + + static const tick_type ticks_per_second; + static const tick_type seconds_per_tick; + static const bool is_subsecond; + + milliseconds( long long ms = 0LL ) : + tv( ms ) + { } + + tick_type count() const + { return tv; } + + template <typename RhsDuration> + milliseconds& operator -=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv -= d.tv * factor / 1000000LL; + return *this; + } + + + template <typename RhsDuration> + milliseconds& operator +=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv += d.tv * factor / 1000000LL; + return *this; + } + + + milliseconds& operator *=( long v ) + { + tv *= v; + return *this; + } + + milliseconds& operator /=( long v ) + { + tv /= v; + return *this; + } + + milliseconds operator -() const + { return milliseconds( -tv ); } + + operator nanoseconds() const + { return nanoseconds(tv * 1000000LL); } + + operator microseconds() const + { return microseconds(tv * 1000LL); } + + bool operator ==( const milliseconds& r ) const + { return tv == r.tv; } + + template <class Duration> + bool operator ==( const Duration& r ) const + { return std::tr2::detail::__op_aux<milliseconds,Duration,std::equal_to<tick_type>,std::tr2::detail::__is_more_precise<milliseconds,Duration>::value>()( *this, r ); } + + bool operator !=( const milliseconds& r ) const + { return tv != r.tv; } + + template <class Duration> + bool operator !=( const Duration& r ) const + { return std::tr2::detail::__op_aux<milliseconds,Duration,std::not_equal_to<tick_type>,std::tr2::detail::__is_more_precise<milliseconds,Duration>::value>()( *this, r ); } + + bool operator <( const milliseconds& r ) const + { return tv < r.tv; } + + template <class Duration> + bool operator <( const Duration& r ) const + { return std::tr2::detail::__op_aux<milliseconds,Duration,std::less<tick_type>,std::tr2::detail::__is_more_precise<milliseconds,Duration>::value>()( *this, r ); } + + bool operator <=( const milliseconds& r ) const + { return tv <= r.tv; } + + template <class Duration> + bool operator <=( const Duration& r ) const + { return std::tr2::detail::__op_aux<milliseconds,Duration,std::less_equal<tick_type>,std::tr2::detail::__is_more_precise<milliseconds,Duration>::value>()( *this, r ); } + + bool operator >( const milliseconds& r ) const + { return tv > r.tv; } + + template <class Duration> + bool operator >( const Duration& r ) const + { return std::tr2::detail::__op_aux<milliseconds,Duration,std::greater<tick_type>,std::tr2::detail::__is_more_precise<milliseconds,Duration>::value>()( *this, r ); } + + bool operator >=( const milliseconds& r ) const + { return tv >= r.tv; } + + template <class Duration> + bool operator >=( const Duration& r ) const + { return std::tr2::detail::__op_aux<milliseconds,Duration,std::greater_equal<tick_type>,std::tr2::detail::__is_more_precise<milliseconds,Duration>::value>()( *this, r ); } + + milliseconds operator +( const milliseconds& r ) const + { return milliseconds( tv + r.tv ); } + + system_time operator +( const system_time& r ) const; + + template <class Duration> + typename std::tr2::detail::__is_more_precise<milliseconds,Duration>::finest_type operator +(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<milliseconds,Duration>::finest_type( + std::tr2::detail::__op_aux2<milliseconds,Duration,std::tr2::detail::add,std::tr2::detail::__is_more_precise<milliseconds,Duration>::value>()( *this, r ) ); + } + + milliseconds operator -( const milliseconds& r ) const + { return milliseconds( tv - r.tv ); } + + template <class Duration> + typename std::tr2::detail::__is_more_precise<milliseconds,Duration>::finest_type operator -(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<milliseconds,Duration>::finest_type( + std::tr2::detail::__op_aux2<milliseconds,Duration,std::tr2::detail::sub,std::tr2::detail::__is_more_precise<milliseconds,Duration>::value>()( *this, r ) ); + } + + milliseconds operator *( long r ) const + { return milliseconds( tv * r ); } + + microseconds operator /( long r ) const + { return milliseconds( tv / r ); } + + private: + tick_type tv; + + friend class nanoseconds; + friend class microseconds; + friend class seconds; + friend class minutes; + friend class hours; +}; + +class seconds +{ + public: + typedef std::tr2::detail::signed_tick_type tick_type; + + static const tick_type ticks_per_second; + static const tick_type seconds_per_tick; + static const bool is_subsecond; + + seconds( long long s = 0LL ) : + tv( s ) + { } + + tick_type count() const + { return tv; } + + template <typename RhsDuration> + seconds& operator -=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv -= d.tv * factor / 1000000000LL; + return *this; + } + + template <typename RhsDuration> + seconds& operator +=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv += d.tv * factor / 1000000000LL; + return *this; + } + + seconds& operator *=( long v ) + { + tv *= v; + return *this; + } + + seconds& operator /=( long v ) + { + tv /= v; + return *this; + } + + seconds operator -() const + { return seconds( -tv ); } + + operator nanoseconds() const + { return nanoseconds(tv * 1000000000LL); } + + operator microseconds() const + { return microseconds(tv * 1000000LL); } + + operator milliseconds() const + { return milliseconds(tv * 1000LL); } + + bool operator ==( const seconds& r ) const + { return tv == r.tv; } + + template <class Duration> + bool operator ==( const Duration& r ) const + { return std::tr2::detail::__op_aux<seconds,Duration,std::equal_to<tick_type>,std::tr2::detail::__is_more_precise<seconds,Duration>::value>()( *this, r ); } + + bool operator !=( const seconds& r ) const + { return tv != r.tv; } + + template <class Duration> + bool operator !=( const Duration& r ) const + { return std::tr2::detail::__op_aux<seconds,Duration,std::not_equal_to<tick_type>,std::tr2::detail::__is_more_precise<seconds,Duration>::value>()( *this, r ); } + + bool operator <( const seconds& r ) const + { return tv < r.tv; } + + template <class Duration> + bool operator <( const Duration& r ) const + { return std::tr2::detail::__op_aux<seconds,Duration,std::less<tick_type>,std::tr2::detail::__is_more_precise<seconds,Duration>::value>()( *this, r ); } + + bool operator <=( const seconds& r ) const + { return tv <= r.tv; } + + template <class Duration> + bool operator <=( const Duration& r ) const + { return std::tr2::detail::__op_aux<seconds,Duration,std::less_equal<tick_type>,std::tr2::detail::__is_more_precise<seconds,Duration>::value>()( *this, r ); } + + bool operator >( const seconds& r ) const + { return tv > r.tv; } + + template <class Duration> + bool operator >( const Duration& r ) const + { return std::tr2::detail::__op_aux<seconds,Duration,std::greater<tick_type>,std::tr2::detail::__is_more_precise<seconds,Duration>::value>()( *this, r ); } + + bool operator >=( const seconds& r ) const + { return tv >= r.tv; } + + template <class Duration> + bool operator >=( const Duration& r ) const + { return std::tr2::detail::__op_aux<seconds,Duration,std::greater_equal<tick_type>,std::tr2::detail::__is_more_precise<seconds,Duration>::value>()( *this, r ); } + + seconds operator +( const seconds& r ) const + { return seconds( tv + r.tv ); } + + system_time operator +( const system_time& r ) const; + + template <class Duration> + typename std::tr2::detail::__is_more_precise<seconds,Duration>::finest_type operator +(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<seconds,Duration>::finest_type( + std::tr2::detail::__op_aux2<seconds,Duration,std::tr2::detail::add,std::tr2::detail::__is_more_precise<seconds,Duration>::value>()( *this, r ) ); + } + + seconds operator -( const seconds& r ) const + { return seconds( tv - r.tv ); } + + template <class Duration> + typename std::tr2::detail::__is_more_precise<seconds,Duration>::finest_type operator -(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<seconds,Duration>::finest_type( + std::tr2::detail::__op_aux2<seconds,Duration,std::tr2::detail::sub,std::tr2::detail::__is_more_precise<seconds,Duration>::value>()( *this, r ) ); + } + + seconds operator *( long r ) const + { return seconds( tv * r ); } + + seconds operator /( long r ) const + { return seconds( tv / r ); } + + private: + tick_type tv; + + friend class nanoseconds; + friend class microseconds; + friend class milliseconds; + friend class minutes; + friend class hours; +}; + +class minutes +{ + public: + typedef std::tr2::detail::signed_tick_type tick_type; + + static const tick_type ticks_per_second; + static const tick_type seconds_per_tick; + static const bool is_subsecond; + + minutes( long long m = 0LL ) : + tv( m ) + { } + + tick_type count() const + { return tv; } + + template <typename RhsDuration> + minutes& operator -=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv -= d.tv * factor / 60000000000LL; + return *this; + } + + template <typename RhsDuration> + minutes& operator +=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv += d.tv * factor / 60000000000LL; + return *this; + } + + + minutes& operator *=( long v ) + { + tv *= v; + return *this; + } + + minutes& operator /=( long v ) + { + tv /= v; + return *this; + } + + minutes operator-() const + { return minutes( -tv ); } + + operator nanoseconds() const + { return nanoseconds(tv * 60000000000LL); } + + operator microseconds() const + { return microseconds(tv * 60000000LL); } + + operator milliseconds() const + { return milliseconds(tv * 60000LL); } + + operator seconds() const + { return seconds(tv * 60LL); } + + bool operator ==( const minutes& r ) const + { return tv == r.tv; } + + template <class Duration> + bool operator ==( const Duration& r ) const + { return std::tr2::detail::__op_aux<minutes,Duration,std::equal_to<tick_type>,std::tr2::detail::__is_more_precise<minutes,Duration>::value>()( *this, r ); } + + bool operator !=( const minutes& r ) const + { return tv != r.tv; } + + template <class Duration> + bool operator !=( const Duration& r ) const + { return std::tr2::detail::__op_aux<minutes,Duration,std::not_equal_to<tick_type>,std::tr2::detail::__is_more_precise<minutes,Duration>::value>()( *this, r ); } + + bool operator <( const minutes& r ) const + { return tv < r.tv; } + + template <class Duration> + bool operator <( const Duration& r ) const + { return std::tr2::detail::__op_aux<minutes,Duration,std::less<tick_type>,std::tr2::detail::__is_more_precise<minutes,Duration>::value>()( *this, r ); } + + bool operator <=( const minutes& r ) const + { return tv <= r.tv; } + + template <class Duration> + bool operator <=( const Duration& r ) const + { return std::tr2::detail::__op_aux<minutes,Duration,std::less_equal<tick_type>,std::tr2::detail::__is_more_precise<minutes,Duration>::value>()( *this, r ); } + + bool operator >( const minutes& r ) const + { return tv > r.tv; } + + template <class Duration> + bool operator >( const Duration& r ) const + { return std::tr2::detail::__op_aux<minutes,Duration,std::greater<tick_type>,std::tr2::detail::__is_more_precise<minutes,Duration>::value>()( *this, r ); } + + bool operator >=( const minutes& r ) const + { return tv >= r.tv; } + + template <class Duration> + bool operator >=( const Duration& r ) const + { return std::tr2::detail::__op_aux<minutes,Duration,std::greater_equal<tick_type>,std::tr2::detail::__is_more_precise<minutes,Duration>::value>()( *this, r ); } + + minutes operator +( const minutes& r ) const + { return minutes( tv + r.tv ); } + + system_time operator +( const system_time& r ) const; + + template <class Duration> + typename std::tr2::detail::__is_more_precise<minutes,Duration>::finest_type operator +(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<minutes,Duration>::finest_type( + std::tr2::detail::__op_aux2<minutes,Duration,std::tr2::detail::add,std::tr2::detail::__is_more_precise<minutes,Duration>::value>()( *this, r ) ); + } + + minutes operator -( const minutes& r ) const + { return minutes( tv - r.tv ); } + + template <class Duration> + typename std::tr2::detail::__is_more_precise<minutes,Duration>::finest_type operator -(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<minutes,Duration>::finest_type( + std::tr2::detail::__op_aux2<minutes,Duration,std::tr2::detail::sub,std::tr2::detail::__is_more_precise<minutes,Duration>::value>()( *this, r ) ); + } + + minutes operator *( long r ) const + { return minutes( tv * r ); } + + minutes operator /( long r ) const + { return minutes( tv / r ); } + + private: + tick_type tv; + + friend class nanoseconds; + friend class microseconds; + friend class milliseconds; + friend class seconds; + friend class hours; +}; + +class hours +{ + public: + typedef std::tr2::detail::signed_tick_type tick_type; + + static const tick_type ticks_per_second; + static const tick_type seconds_per_tick; + static const bool is_subsecond; + + hours( long long h = 0LL ) : + tv( h ) + { } + + tick_type count() const + { return tv; } + + template <typename RhsDuration> + hours& operator -=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv -= d.tv * factor / 3600000000000LL; + return *this; + } + + template <typename RhsDuration> + hours& operator +=( const RhsDuration& d ) + { + static const tick_type factor = RhsDuration::is_subsecond ? nanoseconds::ticks_per_second / RhsDuration::ticks_per_second : nanoseconds::ticks_per_second * RhsDuration::seconds_per_tick; + + tv += d.tv * factor / 3600000000000LL; + return *this; + } + + hours& operator *=( long v ) + { + tv *= v; + return *this; + } + + hours& operator /=( long v ) + { + tv /= v; + return *this; + } + + hours operator -() const + { return hours( -tv ); } + + operator nanoseconds() const + { return nanoseconds(tv * 3600000000000LL); } + + operator microseconds() const + { return microseconds(tv * 3600000000LL); } + + operator milliseconds() const + { return milliseconds(tv * 3600000LL); } + + operator seconds() const + { return seconds(tv * 3600LL); } + + operator minutes() const + { return minutes(tv * 60LL); } + + bool operator ==( const hours& r ) const + { return tv == r.tv; } + + template <class Duration> + bool operator ==( const Duration& r ) const + { return std::tr2::detail::__op_aux<hours,Duration,std::equal_to<tick_type>,std::tr2::detail::__is_more_precise<hours,Duration>::value>()( *this, r ); } + + bool operator !=( const hours& r ) const + { return tv != r.tv; } + + template <class Duration> + bool operator !=( const Duration& r ) const + { return std::tr2::detail::__op_aux<hours,Duration,std::not_equal_to<tick_type>,std::tr2::detail::__is_more_precise<hours,Duration>::value>()( *this, r ); } + + bool operator <( const hours& r ) const + { return tv < r.tv; } + + template <class Duration> + bool operator <( const Duration& r ) const + { return std::tr2::detail::__op_aux<hours,Duration,std::less<tick_type>,std::tr2::detail::__is_more_precise<hours,Duration>::value>()( *this, r ); } + + bool operator <=( const hours& r ) const + { return tv <= r.tv; } + + template <class Duration> + bool operator <=( const Duration& r ) const + { return std::tr2::detail::__op_aux<hours,Duration,std::less_equal<tick_type>,std::tr2::detail::__is_more_precise<hours,Duration>::value>()( *this, r ); } + + bool operator >( const hours& r ) const + { return tv > r.tv; } + + template <class Duration> + bool operator >( const Duration& r ) const + { return std::tr2::detail::__op_aux<hours,Duration,std::greater<tick_type>,std::tr2::detail::__is_more_precise<hours,Duration>::value>()( *this, r ); } + + bool operator >=( const hours& r ) const + { return tv >= r.tv; } + + template <class Duration> + bool operator >=( const Duration& r ) const + { return std::tr2::detail::__op_aux<hours,Duration,std::greater_equal<tick_type>,std::tr2::detail::__is_more_precise<hours,Duration>::value>()( *this, r ); } + + hours operator +( const hours& r ) const + { return hours( tv + r.tv ); } + + system_time operator +( const system_time& r ) const; + + template <class Duration> + typename std::tr2::detail::__is_more_precise<hours,Duration>::finest_type operator +(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<hours,Duration>::finest_type( + std::tr2::detail::__op_aux2<hours,Duration,std::tr2::detail::add,std::tr2::detail::__is_more_precise<hours,Duration>::value>()( *this, r ) ); + } + + hours operator -( const hours& r ) const + { return hours( tv - r.tv ); } + + template <class Duration> + typename std::tr2::detail::__is_more_precise<hours,Duration>::finest_type operator -(const Duration& r) const + { + return typename std::tr2::detail::__is_more_precise<hours,Duration>::finest_type( + std::tr2::detail::__op_aux2<hours,Duration,std::tr2::detail::sub,std::tr2::detail::__is_more_precise<hours,Duration>::value>()( *this, r ) ); + } + + hours operator *( long r ) const + { return hours( tv * r ); } + + hours operator /( long r ) const + { return hours( tv / r ); } + + private: + tick_type tv; + + friend class nanoseconds; + friend class microseconds; + friend class milliseconds; + friend class seconds; + friend class minutes; +}; + +system_time get_system_time(); + +class system_time +{ + private: + struct _adopt_t {}; + + public: + typedef std::tr2::detail::unsigned_tick_type tick_type; + + static const tick_type ticks_per_second; + static const tick_type seconds_per_tick; + static const bool is_subsecond; + + system_time() : + tv( 0ULL ) + { } + explicit system_time( time_t t, nanoseconds ns ) : + tv( t * ticks_per_second + ns.count() ) + { } + explicit system_time( time_t t ) : + tv( t * ticks_per_second ) + { } + + time_t seconds_since_epoch() const + { return static_cast<time_t>( tv / nanoseconds::ticks_per_second ); } + + nanoseconds nanoseconds_since_epoch() const + { return nanoseconds( tv ); } + + bool operator ==(const system_time& rhs) const + { return tv == rhs.tv; } + + bool operator !=(const system_time& rhs) const + { return tv != rhs.tv; } + + bool operator >(const system_time& rhs) const + { return tv > rhs.tv; } + + bool operator >=(const system_time& rhs) const + { return tv >= rhs.tv; } + + bool operator <(const system_time& rhs) const + { return tv < rhs.tv; } + + bool operator <=(const system_time& rhs) const + { return tv <= rhs.tv; } + + nanoseconds operator -(const system_time& rhs) const + { return nanoseconds( tv - rhs.tv ); } + + system_time operator +(const nanoseconds& td) const + { return system_time( tv + td.count(), _adopt_t() ); } + + template <typename Duration> + system_time operator +(const Duration& td) const + { return system_time( tv + static_cast<nanoseconds>( td ).count(), _adopt_t() ); } + + system_time& operator +=(const nanoseconds& td) + { + tv += td.count(); + + return *this; + } + + template <typename Duration> + system_time& operator +=(const Duration& td) + { + tv += static_cast<nanoseconds>( td ).count(); + + return *this; + } + + system_time operator -(const nanoseconds& td) const + { return system_time( tv - td.count() ); } + + template <typename Duration> + system_time operator -(const Duration& td) const + { return system_time( tv - static_cast<nanoseconds>( td ).count() ); } + + system_time& operator -=(const nanoseconds& td) + { + tv -= td.count(); + + return *this; + } + + template <typename Duration> + system_time& operator -=(const Duration& td) + { + tv -= static_cast<nanoseconds>( td ).count(); + + return *this; + } + + private: + system_time( tick_type _v, const _adopt_t& ) : + tv( _v ) + { } + + tick_type tv; + + friend system_time get_system_time(); +}; + +inline nanoseconds operator *( long lhs, const nanoseconds& rhs ) +{ return nanoseconds( rhs.count() * lhs ); } + +inline microseconds operator *( long lhs, const microseconds& rhs ) +{ return microseconds( rhs.count() * lhs ); } + +inline milliseconds operator *( long lhs, const milliseconds& rhs ) +{ return milliseconds( rhs.count() * lhs ); } + +inline seconds operator *( long lhs, const seconds& rhs ) +{ return seconds( rhs.count() * lhs ); } + +inline minutes operator *( long lhs, const minutes& rhs ) +{ return minutes( rhs.count() * lhs ); } + +inline hours operator *( long lhs, const hours& rhs ) +{ return hours( rhs.count() * lhs ); } + +} // namespace tr2 + +} // namespace std + +#endif // __MT_DATE_TIME Modified: branches/wg21-thread/include/mt/mutex =================================================================== --- branches/wg21-thread/include/mt/mutex 2008-02-26 13:06:33 UTC (rev 1816) +++ branches/wg21-thread/include/mt/mutex 2008-02-26 14:39:44 UTC (rev 1817) @@ -1,7 +1,7 @@ -// -*- C++ -*- Time-stamp: <07/09/15 10:03:40 ptr> +// -*- C++ -*- Time-stamp: <08/02/24 23:48:23 ptr> /* - * Copyright (c) 1997-1999, 2002-2007 + * Copyright (c) 1997-1999, 2002-2008 * Petr Ovtchenkov * * Portion Copyright (c) 1999-2001 @@ -9,23 +9,22 @@ * * Licensed under the Academic Free License version 3.0 * + * Derived from original <mt/xmt.h> of 'complement' project + * [http://complement.sourceforge.net] + * to make it close to JTC1/SC22/WG21 working draft + * [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2497.html] */ -#ifndef __XMT_H -#define __XMT_H +#ifndef __MUTEX_H +#define __MUTEX_H #ifndef __config_feature_h #include <config/feature.h> #endif -#include <memory> #include <cstddef> #include <stdexcept> -#if !defined(_STLPORT_VERSION) && !defined(__STATIC_CAST) -# define __STATIC_CAST(t,v) static_cast<t>(v) -#endif - #ifdef WIN32 # include <windows.h> # include <memory> @@ -35,81 +34,17 @@ #endif // WIN32 #ifdef __unix -# if defined( _REENTRANT ) && !defined(_NOTHREADS) -# ifdef _PTHREADS -# include <pthread.h> -# include <semaphore.h> -# include <sched.h> -# else -# include <thread.h> -# include <synch.h> -# endif -# elif !defined(_NOTHREADS) // !_REENTRANT -# define _NOTHREADS -# endif -// # define __DLLEXPORT +# include <pthread.h> +# include <sched.h> #endif // __unix #include <cerrno> +#include <mt/system_error> -#include <mt/time.h> +namespace std { -#ifdef _REENTRANT +namespace tr2 { -# define MT_REENTRANT(point,nm) xmt::scoped_lock nm(point) -# define MT_LOCK(point) point.lock() -# define MT_UNLOCK(point) point.unlock() - -#else // !_REENTRANT - -# define MT_REENTRANT(point,nm) ((void)0) -# define MT_REENTRANT_RS(point,nm) ((void)0) -# define MT_LOCK(point) ((void)0) -# define MT_UNLOCK(point) ((void)0) - -#endif // _REENTRANT - -#include <signal.h> - -extern "C" { - -#ifndef SIG_PF // sys/signal.h - -# ifdef WIN32 -typedef void __cdecl SIG_FUNC_TYP(int); -# else -typedef void SIG_FUNC_TYP(int); -# endif -typedef SIG_FUNC_TYP *SIG_TYP; -# define SIG_PF SIG_TYP - -# ifndef SIG_DFL -# define SIG_DFL (SIG_PF)0 -# endif -# ifndef SIG_ERR -# define SIG_ERR (SIG_PF)-1 -# endif -# ifndef SIG_IGN -# define SIG_IGN (SIG_PF)1 -# endif -# ifndef SIG_HOLD -# define SIG_HOLD (SIG_PF)2 -# endif -#endif // SIG_PF - -typedef void si... [truncated message content] |
From: <com...@us...> - 2008-02-26 13:06:36
|
Revision: 1816 http://complement.svn.sourceforge.net/complement/?rev=1816&view=rev Author: complement Date: 2008-02-26 05:06:33 -0800 (Tue, 26 Feb 2008) Log Message: ----------- take into account ${DESTDIR} Modified Paths: -------------- trunk/complement/explore/Makefiles/ChangeLog trunk/complement/explore/Makefiles/gmake/targetdirs.mak trunk/complement/explore/configure Modified: trunk/complement/explore/Makefiles/ChangeLog =================================================================== --- trunk/complement/explore/Makefiles/ChangeLog 2008-02-26 10:55:11 UTC (rev 1815) +++ trunk/complement/explore/Makefiles/ChangeLog 2008-02-26 13:06:33 UTC (rev 1816) @@ -2,8 +2,10 @@ * gmake/gcc.mak: use more convenient option -dumpversion to detect compiler's revision; check that -fuse-cxa-atexit - really required; remove -fident option. + really required; remove -fident option; + * gmake/targetdirs.mak: take into account DESTDIR. + 2008-01-17 Petr Ovtchenkov <pt...@is...> * gmake/topdoc.mak: rules to generate mps from mp, that was made Modified: trunk/complement/explore/Makefiles/gmake/targetdirs.mak =================================================================== --- trunk/complement/explore/Makefiles/gmake/targetdirs.mak 2008-02-26 10:55:11 UTC (rev 1815) +++ trunk/complement/explore/Makefiles/gmake/targetdirs.mak 2008-02-26 13:06:33 UTC (rev 1816) @@ -1,6 +1,6 @@ -# Time-stamp: <06/11/03 18:47:05 ptr> +# Time-stamp: <08/02/26 15:42:24 yeti> # -# Copyright (c) 1997-1999, 2002, 2003, 2005-2007 +# Copyright (c) 1997-1999, 2002, 2003, 2005-2008 # Petr Ovtchenkov # # Portion Copyright (c) 1999-2001 @@ -37,7 +37,7 @@ endif # BASE_INSTALL_DIR ?= ${SRCROOT}/build/$(TARGET_NAME) -BASE_INSTALL_DIR ?= /usr/local +BASE_INSTALL_DIR ?= $(DESTDIR)/usr/local BASE_INSTALL_LIB_DIR ?= ${BASE_INSTALL_DIR} BASE_INSTALL_BIN_DIR ?= ${BASE_INSTALL_DIR} Modified: trunk/complement/explore/configure =================================================================== --- trunk/complement/explore/configure 2008-02-26 10:55:11 UTC (rev 1815) +++ trunk/complement/explore/configure 2008-02-26 13:06:33 UTC (rev 1816) @@ -1,6 +1,6 @@ #!/bin/sh -# Time-stamp: <08/01/17 01:11:57 ptr> +# Time-stamp: <08/02/26 16:02:32 yeti> base=`cd \`dirname $0\`; echo $PWD` @@ -12,7 +12,7 @@ write_option() { target=`echo $1 | sed -e 's/^[^=]*=//'` - echo $2 := $target >> ${configmak} + echo $2 := $3$target >> ${configmak} } write_over_option() { @@ -84,12 +84,12 @@ # write_option "${PWD}/external/STLport" STLPORT_DIR write_option "1" WITHOUT_STLPORT fi - # write_option "${PWD}/build/" BASE_INSTALL_DIR + # write_option "${PWD}/build/" BASE_INSTALL_DIR '${DESTDIR}' if [ "$compiler_family_set" = "" ]; then write_option gcc COMPILER_NAME fi # if [ "$prefix_set" = "" ]; then - # write_option "/usr/local" BASE_INSTALL_DIR + # write_option "/usr/local" BASE_INSTALL_DIR '${DESTDIR}' # fi } @@ -192,17 +192,17 @@ compiler_family_set=y ;; --prefix=*) - write_option "$option" BASE_INSTALL_DIR + write_option "$option" BASE_INSTALL_DIR '${DESTDIR}' # prefix_set=y ;; --bindir=*) - write_option "$option" INSTALL_BIN_DIR + write_option "$option" INSTALL_BIN_DIR '${DESTDIR}' ;; --libdir=*) - write_option "$option" INSTALL_LIB_DIR + write_option "$option" INSTALL_LIB_DIR '${DESTDIR}' ;; --includedir=*) - write_option "$option" INSTALL_HDR_DIR + write_option "$option" INSTALL_HDR_DIR '${DESTDIR}' ;; esac done This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-02-26 10:55:20
|
Revision: 1815 http://complement.svn.sourceforge.net/complement/?rev=1815&view=rev Author: complement Date: 2008-02-26 02:55:11 -0800 (Tue, 26 Feb 2008) Log Message: ----------- use more convenient option -dumpversion to detect compiler's revision; check that -fuse-cxa-atexit really required; remove -fident option Modified Paths: -------------- trunk/complement/explore/Makefiles/ChangeLog trunk/complement/explore/Makefiles/gmake/gcc.mak Modified: trunk/complement/explore/Makefiles/ChangeLog =================================================================== --- trunk/complement/explore/Makefiles/ChangeLog 2008-02-20 09:47:34 UTC (rev 1814) +++ trunk/complement/explore/Makefiles/ChangeLog 2008-02-26 10:55:11 UTC (rev 1815) @@ -1,3 +1,9 @@ +2008-02-26 Petr Ovtchenkov <pt...@is...> + + * gmake/gcc.mak: use more convenient option -dumpversion + to detect compiler's revision; check that -fuse-cxa-atexit + really required; remove -fident option. + 2008-01-17 Petr Ovtchenkov <pt...@is...> * gmake/topdoc.mak: rules to generate mps from mp, that was made Modified: trunk/complement/explore/Makefiles/gmake/gcc.mak =================================================================== --- trunk/complement/explore/Makefiles/gmake/gcc.mak 2008-02-20 09:47:34 UTC (rev 1814) +++ trunk/complement/explore/Makefiles/gmake/gcc.mak 2008-02-26 10:55:11 UTC (rev 1815) @@ -1,4 +1,4 @@ -# Time-stamp: <07/07/12 10:51:42 ptr> +# Time-stamp: <08/02/26 13:46:36 yeti> # # Copyright (c) 1997-1999, 2002, 2003, 2005-2008 # Petr Ovtchenkov @@ -31,30 +31,22 @@ AS := ${TARGET_OS}-${AS} endif -ifeq ($(OSNAME), darwin) CXX_VERSION := $(shell ${CXX} -dumpversion) -# TODO: ensure PANTHER's gcc compatibility... -CXX_VERSION_MAJOR := $(shell ${CXX} -dumpversion | awk 'BEGIN { FS = "."; } { print $1; }') -CXX_VERSION_MINOR := $(shell ${CXX} -dumpversion | awk 'BEGIN { FS = "."; } { print $2; }') -CXX_VERSION_PATCH := $(shell ${CXX} -dumpversion | awk 'BEGIN { FS = "."; } { print $3; }') +CXX_VERSION_MAJOR := $(shell echo ${CXX_VERSION} | awk 'BEGIN { FS = "."; } { print $$1; }') +CXX_VERSION_MINOR := $(shell echo ${CXX_VERSION} | awk 'BEGIN { FS = "."; } { print $$2; }') +CXX_VERSION_PATCH := $(shell echo ${CXX_VERSION} | awk 'BEGIN { FS = "."; } { print $$3; }') + +# Check that we need option -fuse-cxa-atexit for compiler +_CXA_ATEXIT := $(shell ${CXX} -v 2>&1 | grep -q -e "--enable-__cxa_atexit" || echo "-fuse-cxa-atexit") + +ifeq ($(OSNAME), darwin) # This is to differentiate Apple-builded compiler from original -# compiler (it's has different behaviour) +# GNU compiler (it's has different behaviour) ifneq ("$(shell ${CXX} -v 2>&1 | grep Apple)", "") GCC_APPLE_CC := 1 endif -else -CXX_VERSION := $(shell ${CXX} --version | grep GCC | awk '{ print $$3; }') - -ifeq ($(CXX_VERSION),) -# 2.95 report only version -CXX_VERSION := $(shell ${CXX} --version) endif -CXX_VERSION_MAJOR := $(shell echo ${CXX_VERSION} | awk 'BEGIN { FS = "."; } { print $$1; }') -CXX_VERSION_MINOR := $(shell echo ${CXX_VERSION} | awk 'BEGIN { FS = "."; } { print $$2; }') -CXX_VERSION_PATCH := $(shell echo ${CXX_VERSION} | awk 'BEGIN { FS = "."; } { print $$3; }') -endif - DEFS ?= OPT ?= @@ -78,7 +70,7 @@ dbg-shared : RCFLAGS += -DBUILD=g -DBUILD_INFOS=-g stldbg-shared : RCFLAGS += -DBUILD=stlg -DBUILD_INFOS="-g -D_STLP_DEBUG" RC_OUTPUT_OPTION = -o $@ -CXXFLAGS = -Wall -Wsign-promo -Wcast-qual -fexceptions -fident +CXXFLAGS = -Wall -Wsign-promo -Wcast-qual -fexceptions ifeq ($(OSREALNAME), mingw) CCFLAGS += -mthreads CFLAGS += -mthreads @@ -104,30 +96,30 @@ ifeq ($(OSNAME),sunos) CCFLAGS = -pthreads $(OPT) CFLAGS = -pthreads $(OPT) -# CXXFLAGS = -pthreads -nostdinc++ -fexceptions -fident $(OPT) -CXXFLAGS = -pthreads -fexceptions -fident $(OPT) +# CXXFLAGS = -pthreads -nostdinc++ -fexceptions $(OPT) +CXXFLAGS = -pthreads -fexceptions $(OPT) endif ifeq ($(OSNAME),linux) CCFLAGS = -pthread $(OPT) CFLAGS = -pthread $(OPT) -# CXXFLAGS = -pthread -nostdinc++ -fexceptions -fident $(OPT) -CXXFLAGS = -pthread -fexceptions -fident $(OPT) +# CXXFLAGS = -pthread -nostdinc++ -fexceptions $(OPT) +CXXFLAGS = -pthread -fexceptions $(OPT) endif ifeq ($(OSNAME),openbsd) CCFLAGS = -pthread $(OPT) CFLAGS = -pthread $(OPT) -# CXXFLAGS = -pthread -nostdinc++ -fexceptions -fident $(OPT) -CXXFLAGS = -pthread -fexceptions -fident $(OPT) +# CXXFLAGS = -pthread -nostdinc++ -fexceptions $(OPT) +CXXFLAGS = -pthread -fexceptions $(OPT) endif ifeq ($(OSNAME),freebsd) CCFLAGS = -pthread $(OPT) CFLAGS = -pthread $(OPT) DEFS += -D_REENTRANT -# CXXFLAGS = -pthread -nostdinc++ -fexceptions -fident $(OPT) -CXXFLAGS = -pthread -fexceptions -fident $(OPT) +# CXXFLAGS = -pthread -nostdinc++ -fexceptions $(OPT) +CXXFLAGS = -pthread -fexceptions $(OPT) endif ifeq ($(OSNAME),darwin) @@ -143,8 +135,8 @@ ifeq ($(OSNAME),hp-ux) CCFLAGS = -pthread $(OPT) CFLAGS = -pthread $(OPT) -# CXXFLAGS = -pthread -nostdinc++ -fexceptions -fident $(OPT) -CXXFLAGS = -pthread -fexceptions -fident $(OPT) +# CXXFLAGS = -pthread -nostdinc++ -fexceptions $(OPT) +CXXFLAGS = -pthread -fexceptions $(OPT) endif #ifeq ($(CXX_VERSION_MAJOR),3) @@ -165,7 +157,7 @@ # Required for correct order of static objects dtors calls: ifeq ("$(findstring $(OSNAME),darwin windows)","") ifneq ($(CXX_VERSION_MAJOR),2) -CXXFLAGS += -fuse-cxa-atexit +CXXFLAGS += $(_CXA_ATEXIT) endif endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-02-20 09:47:43
|
Revision: 1814 http://complement.svn.sourceforge.net/complement/?rev=1814&view=rev Author: complement Date: 2008-02-20 01:47:34 -0800 (Wed, 20 Feb 2008) Log Message: ----------- turn __FIT_PTHREADS, if _PTHREADS found Modified Paths: -------------- trunk/complement/explore/include/config/_freebsd.h trunk/complement/explore/include/config/_linux.h trunk/complement/explore/include/config/_openbsd.h trunk/complement/explore/include/config/_windows.h Modified: trunk/complement/explore/include/config/_freebsd.h =================================================================== --- trunk/complement/explore/include/config/_freebsd.h 2008-02-11 17:39:41 UTC (rev 1813) +++ trunk/complement/explore/include/config/_freebsd.h 2008-02-20 09:47:34 UTC (rev 1814) @@ -1,21 +1,12 @@ -/* Time-stamp: <05/12/12 10:46:44 ptr> */ +/* Time-stamp: <08/02/20 09:58:33 ptr> */ /* * - * Copyright (c) 2003, 2005 + * Copyright (c) 2003-2008 * Petr Ovtchenkov * - * Licensed under the Academic Free License Version 2.1 + * Licensed under the Academic Free License version 3.0 * - * This material is provided "as is", with absolutely no warranty expressed - * or implied. Any use is at your own risk. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. - * */ #ifndef __config__freebsd_h @@ -32,6 +23,7 @@ #endif #if defined(_PTHREADS) +# define __FIT_PTHREADS # ifndef __USE_UNIX98 # define __USE_UNIX98 # endif Modified: trunk/complement/explore/include/config/_linux.h =================================================================== --- trunk/complement/explore/include/config/_linux.h 2008-02-11 17:39:41 UTC (rev 1813) +++ trunk/complement/explore/include/config/_linux.h 2008-02-20 09:47:34 UTC (rev 1814) @@ -1,8 +1,8 @@ -/* Time-stamp: <07/01/31 23:51:12 ptr> */ +/* Time-stamp: <08/02/20 09:57:38 ptr> */ /* * - * Copyright (c) 2003-2007 + * Copyright (c) 2003-2008 * Petr Ovtchenkov * * Licensed under the Academic Free License version 3.0 @@ -35,6 +35,7 @@ # define __USE_UNIX98 # endif */ +# define __FIT_PTHREADS /* This feature exist at least since glibc 2.2.4 */ # define __FIT_XSI_THR /* Unix 98 or X/Open System Interfaces Extention */ # ifdef __USE_XOPEN2K Modified: trunk/complement/explore/include/config/_openbsd.h =================================================================== --- trunk/complement/explore/include/config/_openbsd.h 2008-02-11 17:39:41 UTC (rev 1813) +++ trunk/complement/explore/include/config/_openbsd.h 2008-02-20 09:47:34 UTC (rev 1814) @@ -1,28 +1,17 @@ -// -*- C++ -*- Time-stamp: <05/09/02 00:46:15 ptr> +// -*- C++ -*- Time-stamp: <08/02/20 10:01:25 ptr> /* * - * Copyright (c) 2003 + * Copyright (c) 2003-2008 * Petr Ovtchenkov * - * Licensed under the Academic Free License Version 2.1 + * Licensed under the Academic Free License version 3.0 * - * This material is provided "as is", with absolutely no warranty expressed - * or implied. Any use is at your own risk. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. - * */ #ifndef __config__openbsd_h #define __config__openbsd_h -#ident "@(#)$Id$" - #define __FIT__P_PROBLEM // Hide __P from sys/cdefs.h. Workaround for glibc. #ifndef __unix @@ -34,6 +23,7 @@ #endif #if defined(_PTHREADS) +# define __FIT_PTHREADS # ifndef __USE_UNIX98 # define __USE_UNIX98 # endif Modified: trunk/complement/explore/include/config/_windows.h =================================================================== --- trunk/complement/explore/include/config/_windows.h 2008-02-11 17:39:41 UTC (rev 1813) +++ trunk/complement/explore/include/config/_windows.h 2008-02-20 09:47:34 UTC (rev 1814) @@ -1,21 +1,12 @@ -/* Time-stamp: <03/06/29 19:53:27 ptr> */ +/* Time-stamp: <08/02/20 10:02:49 ptr> */ /* * - * Copyright (c) 2003 + * Copyright (c) 2003-2008 * Petr Ovtchenkov * - * Licensed under the Academic Free License Version 2.1 + * Licensed under the Academic Free License version 3.0 * - * This material is provided "as is", with absolutely no warranty expressed - * or implied. Any use is at your own risk. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. - * */ #ifndef __config__windows_h This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-02-11 17:39:46
|
Revision: 1813 http://complement.svn.sourceforge.net/complement/?rev=1813&view=rev Author: complement Date: 2008-02-11 09:39:41 -0800 (Mon, 11 Feb 2008) Log Message: ----------- base for branch, conversion mt -> wg21 working draft Added Paths: ----------- branches/wg21-thread/lib/mt/thread.cc Copied: branches/wg21-thread/lib/mt/thread.cc (from rev 1812, branches/wg21-thread/lib/mt/xmt.cc) =================================================================== --- branches/wg21-thread/lib/mt/thread.cc (rev 0) +++ branches/wg21-thread/lib/mt/thread.cc 2008-02-11 17:39:41 UTC (rev 1813) @@ -0,0 +1,944 @@ +// -*- C++ -*- Time-stamp: <07/09/15 10:16:39 ptr> + +/* + * Copyright (c) 1997-1999, 2002-2007 + * Petr Ovtchenkov + * + * Portion Copyright (c) 1999-2001 + * Parallel Graphics Ltd. + * + * Licensed under the Academic Free License version 3.0 + * + */ + +#include <config/feature.h> + +#include <sys/types.h> +#ifndef _WIN32 +# include <unistd.h> +#endif +#include <fcntl.h> + +#include <mt/xmt.h> +#include <mt/callstack.h> + +#include <cstring> +#ifndef _WIN32 +# include <ostream> +#endif + +#include <iostream> +#include <iomanip> +#include <sstream> +#include <memory> +#include <functional> +#include <cerrno> +#include <string> + +#ifdef __linux +# ifndef __USE_GNU +# define __USE_GNU +# endif +# include <sys/time.h> +#endif + +#include <stdio.h> +#include <syscall.h> + +#include <cmath> // for time operations + +#ifdef WIN32 +# pragma warning( disable : 4290) +// using namespace std; +#endif + +/* +extern "C" { +#ifdef WIN32 + typedef unsigned long (__stdcall *entrance_type_C)( void * ); +#else + typedef void *(*entrance_type_C)( void * ); +#endif +} +*/ + +#ifdef WIN32 +# if 0 +extern "C" int APIENTRY +DllMain( HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved ) +{ + return TRUE; // ok +} +# endif +#endif + +namespace xmt { +namespace detail { + +int Init_count = 0; + +// problem: ::getpid() really return cached value, so pid returned may be +// parent's pid really. I use syscall here and rewrite it during Thread::fork(). + +static pid_t _pid = syscall( SYS_getpid ); +static pid_t _ppid = syscall( SYS_getppid ); + +xmt::Thread::thread_key_type _mt_key = __STATIC_CAST(xmt::Thread::thread_key_type,-1); +# ifndef __FIT_WIN32THREADS +void *_uw_save = 0; +# endif + +#ifdef _PTHREADS +xmt::mutex _F_lock; +# define _F_locklock xmt::detail::_F_lock.lock(); +# define _F_lockunlock xmt::detail::_F_lock.unlock(); +#endif + +#ifdef __FIT_UITHREADS +# error "Unimplemented" +#endif + +#if defined(__FIT_WIN32THREADS) +# define _F_locklock +# define _F_lockunlock +#endif + +#ifdef __FIT_PSHARED_MUTEX +std::string _notpshared( "Platform not support process shared mutex" ); +#endif + +#ifdef __FIT_XSI_THR +std::string _notrecursive( "Platform not support recursive mutex" ); +#endif + +} // namespace detail +} // namespace xmt + +extern "C" void __at_fork_prepare() +{ +#ifdef _PTHREADS + if ( xmt::detail::Init_count > 0 ) { + xmt::detail::_uw_save = pthread_getspecific( xmt::detail::_mt_key ); + } +#endif +} + +extern "C" void __at_fork_parent() +{ +#ifdef _PTHREADS +#endif +} + +extern "C" void __at_fork_child() +{ +#ifdef _PTHREADS + if ( xmt::detail::Init_count > 0 ) { + // otherwise we do it in Thread::Init::Init() below +# if !(defined(__FreeBSD__) || defined(__OpenBSD__)) + // I am misunderstand this point, Solaris 7 require this (to be restored) + + // pthread_atfork( __at_fork_prepare, __at_fork_parent, __at_fork_child ); + + // while Linux (and other) inherit this setting from parent process? + // At least Linux glibc 2.2.5 try to made lock in recursive + // call of pthread_atfork +# else +// should be fixed... +# endif // !(__FreeBSD__ || __OpenBSD__) + pthread_key_create( &xmt::detail::_mt_key, 0 ); + pthread_setspecific( xmt::detail::_mt_key, xmt::detail::_uw_save ); + xmt::detail::_uw_save = 0; + // Note, that only calling thread inherited when we use POSIX: + xmt::detail::Init_count = 1; // i.e. only ONE (calling) thread... + } +#endif +} + +namespace xmt { + +#ifndef _WIN32 +using std::cerr; +using std::endl; +#endif + +char *Init_buf[32]; +int& Thread::Init::_count( detail::Init_count ); // trick to avoid friend declarations + +const std::string msg1( "Can't create thread" ); +const std::string msg2( "Can't fork" ); + +// __FIT_DECLSPEC +// void signal_throw( int sig ) throw( int ) +// { +// throw sig; +// } + + +Thread::Init::Init() +{ + // This is performance problem, let's consider replace to atomic lock... + _F_locklock + + if ( _count++ == 0 ) { +#ifdef __FIT_UITHREADS + thr_keycreate( &_mt_key, 0 ); +#endif +#ifdef _PTHREADS +# if !(defined(__FreeBSD__) || defined(__OpenBSD__)) + if ( pthread_atfork( __at_fork_prepare, __at_fork_parent, __at_fork_child ) ) { + _F_lockunlock + throw std::runtime_error( "Problems with pthread_atfork" ); + } +# endif // !(__FreeBSD__ || __OpenBSD__) + pthread_key_create( &_mt_key, 0 ); +#endif +#ifdef __FIT_WIN32THREADS + _mt_key = TlsAlloc(); +#endif + Thread::_self_idx = Thread::xalloc(); + } + + _F_lockunlock +} + +Thread::Init::~Init() +{ + // This is performance problem, let's consider replace to atomic lock... + _F_locklock + + if ( --_count == 0 ) { +#ifdef __FIT_WIN32THREADS + TlsFree( _mt_key ); +#endif +#ifdef _PTHREADS + pthread_key_delete( _mt_key ); +#endif + } + + _F_lockunlock +} + +Thread::alloc_type Thread::alloc; +int Thread::_idx = 0; +int Thread::_self_idx = 0; +mutex Thread::_idx_lock; + +#ifdef __FIT_WIN32THREADS +const Thread::thread_id_type Thread::bad_thread_id = INVALID_HANDLE_VALUE; +#endif // __FIT_WIN32THREADS + +#if defined(__FIT_UITHREADS) || defined(_PTHREADS) +# if !(defined(__FreeBSD__) || defined(__OpenBSD__)) +const Thread::thread_id_type Thread::bad_thread_id = __STATIC_CAST(Thread::thread_id_type,-1); +# else // __FreeBSD__ || __OpenBSD__ +// pthread_t is defined as 'typedef struct pthread *pthread_t;' +const Thread::thread_id_type Thread::bad_thread_id = __STATIC_CAST(Thread::thread_id_type,0); +# endif // !(__FreeBSD__ || __OpenBSD__) +#endif // __FIT_UITHREADS || _PTHREADS + +Thread::thread_key_type& Thread::_mt_key( detail::_mt_key ); + +__FIT_DECLSPEC +void Thread::_dealloc_uw() +{ + if ( uw_alloc_size != 0 ) { + // _STLP_ASSERT( _id != bad_thread_id ); + // _STLP_ASSERT( is_self() ); +#ifdef __FIT_UITHREADS + _uw_alloc_type *user_words; + thr_getspecific( _mt_key, &(static_cast<void *>(user_words)) ); +#endif +#ifdef _PTHREADS + _uw_alloc_type *user_words = static_cast<_uw_alloc_type *>(pthread_getspecific( _mt_key )); +#endif +#ifdef __FIT_WIN32THREADS + _uw_alloc_type *user_words = static_cast<_uw_alloc_type *>(TlsGetValue( _mt_key )); +#endif + alloc.deallocate( user_words, uw_alloc_size ); + user_words = 0; + uw_alloc_size = 0; + } +} + +__FIT_DECLSPEC +Thread::_uw_alloc_type *Thread::_alloc_uw( int __idx ) +{ + // _STLP_ASSERT( _id != bad_thread_id ); + // _STLP_ASSERT( is_self() ); + + _uw_alloc_type *user_words; + + if ( uw_alloc_size == 0 ) { + uw_alloc_size = sizeof( _uw_alloc_type ) * (__idx + 1); +#if !defined(_STLP_VERSION) && defined(_MSC_VER) + user_words = alloc.allocate( uw_alloc_size, (void *)0 ); +#else + user_words = alloc.allocate( uw_alloc_size ); +#endif + std::fill( user_words, user_words + uw_alloc_size, 0 ); +#ifdef __FIT_UITHREADS + thr_setspecific( _mt_key, user_words ); +#endif +#ifdef _PTHREADS + pthread_setspecific( _mt_key, user_words ); +#endif +#ifdef __FIT_WIN32THREADS + TlsSetValue( _mt_key, user_words ); +#endif + } else { +#ifdef __FIT_UITHREADS + thr_getspecific( _mt_key, &(static_cast<void *>(user_words)) ); +#endif +#ifdef _PTHREADS + user_words = static_cast<_uw_alloc_type *>(pthread_getspecific( _mt_key )); +#endif +#ifdef __FIT_WIN32THREADS + user_words = static_cast<_uw_alloc_type *>(TlsGetValue( _mt_key )); +#endif + if ( (__idx + 1) * sizeof( _uw_alloc_type ) > uw_alloc_size ) { + size_t tmp = sizeof( _uw_alloc_type ) * (__idx + 1); +#if !defined(_STLP_VERSION) && defined(_MSC_VER) + _uw_alloc_type *_mtmp = alloc.allocate( tmp, (void *)0 ); +#else + _uw_alloc_type *_mtmp = alloc.allocate( tmp ); +#endif + std::copy( user_words, user_words + uw_alloc_size, _mtmp ); + std::fill( _mtmp + uw_alloc_size, _mtmp + tmp, 0 ); + alloc.deallocate( user_words, uw_alloc_size ); + user_words = _mtmp; + uw_alloc_size = tmp; +#ifdef __FIT_UITHREADS + thr_setspecific( _mt_key, user_words ); +#endif +#ifdef _PTHREADS + pthread_setspecific( _mt_key, user_words ); +#endif +#ifdef __FIT_WIN32THREADS + TlsSetValue( _mt_key, user_words ); +#endif + } + } + + return user_words + __idx; +} + +__FIT_DECLSPEC +Thread::Thread( unsigned __f ) : + _id( bad_thread_id ), + _rip_id( bad_thread_id ), + _entrance( 0 ), + _param( 0 ), + _param_sz( 0 ), + _flags( __f ), + _stack_sz( 0 ), + uw_alloc_size( 0 ) +{ + new( Init_buf ) Init(); +} + +__FIT_DECLSPEC +Thread::Thread( Thread::entrance_type entrance, const void *p, size_t psz, unsigned __f, size_t stack_sz ) : + _id( bad_thread_id ), + _rip_id( bad_thread_id ), + _entrance( entrance ), + _param( 0 ), + _param_sz( 0 ), + _flags( __f ), + _stack_sz( stack_sz ), + uw_alloc_size( 0 ) +{ + new( Init_buf ) Init(); + // Locker lk( _llock ); + _create( p, psz ); +} + +__FIT_DECLSPEC +Thread::~Thread() +{ + Thread::join(); + + if ( (_flags & (daemon | detached)) != 0 ) { // not joinable + // Locker lk( _llock ); + if ( _id != bad_thread_id ) { // still run? + cerr << "Suspected crash of daemon thread, threas id " << _id << endl; +#ifdef __FIT_CREATE_THREAD_STACK_INFO + cerr << "Stack when thread was created:\n" << _stack_on_create << endl; +#endif + std::stringstream s; + callstack( s ); + cerr << "Current stack is:\n" << s.str() << endl; + } + } + + ((Init *)Init_buf)->~Init(); + + // _STLP_ASSERT( _id == bad_thread_id ); + // Thread::kill( SIGTERM ); + // Thread::signal_exit( SIGTERM ); // call handler directly, avoid signal delivery +} + +__FIT_DECLSPEC +bool Thread::is_self() +{ + // Locker lk( _llock ); +#ifdef _PTHREADS + return (_id != bad_thread_id) && (_id == pthread_self()); +#elif defined(__FIT_UITHREADS) + return (_id != bad_thread_id) && (_id == thr_self()); +#elif defined(__FIT_WIN32THREADS) + return (_id != bad_thread_id) && (_id == GetCurrentThread()); +#else +# error "Fix me! (replace pthread_self())" +#endif +} + +__FIT_DECLSPEC +void Thread::launch( entrance_type entrance, const void *p, size_t psz, size_t stack_sz ) +{ + // Locker lk( _llock ); + _stack_sz = stack_sz; + if ( _not_run() ) { + _entrance = entrance; + _create( p, psz ); + } +} + +__FIT_DECLSPEC +Thread::ret_t Thread::join() +{ + ret_t rt = 0; + +#ifdef __FIT_WIN32THREADS + if ( !_not_run() ) { + WaitForSingleObject( _id, -1 ); + GetExitCodeThread( _id, &rt ); + CloseHandle( _id ); + // Locker lk( _llock ); + _id = bad_thread_id; + } +#endif // __FIT_WIN32THREADS +#if defined(__FIT_UITHREADS) || defined(_PTHREADS) + if ( is_join_req() ) { +# ifdef _PTHREADS + pthread_join( _rip_id, &rt ); +# endif +# ifdef __FIT_UITHREADS + thr_join( _rip_id, 0, &rt ); +# endif + // Locker lk( _llock ); + scoped_lock lk( _rip_id_lock ); + _rip_id = bad_thread_id; + } +#endif // __FIT_UITHREADS || PTHREADS + + return rt; +} + +__FIT_DECLSPEC +int Thread::suspend() +{ + if ( good() ) { + // to do: fix possible race with _id, when it used here +#ifdef __FIT_WIN32THREADS + return SuspendThread( _id ); +#endif +#ifdef _PTHREADS + // sorry, POSIX threads don't have pthread_{suspend,continue} calls, so it should + // be simulated via condwait +# ifdef __hpux + // but HP-UX 11.00 implementation of POSIX threads has extention (or it in X/Open?) + // pthread_{suspend,continue}, I use it: + return pthread_suspend( _id ); +# else + _suspend.set( false ); + return _suspend.try_wait(); // thr_suspend and pthread_cond_wait return 0 in success +# endif +#endif // __STL_PTHREADS +#ifdef __FIT_UITHREADS + return thr_suspend( _id ); +#endif + } + + return -1; +} + +__FIT_DECLSPEC +int Thread::resume() +{ + if ( good() ) { + // to do: fix possible race with _id, when it used here +#ifdef __FIT_WIN32THREADS + return ResumeThread( _id ); +#endif +#ifdef _PTHREADS + // sorry, POSIX threads don't have pthread_{suspend,continue} calls, so it should + // be simulated via condwait +# ifdef __hpux + // but HP-UX 11.00 implementation of POSIX threads has extention (or it in X/Open?) + // pthread_{suspend,continue}, I use it: + return pthread_continue( _id ); +# else + return _suspend.set( true ) == false ? 0 : -1; // less syscall than _suspend.signal(); +# endif + +#endif +#ifdef __FIT_UITHREADS + return thr_continue( _id ); +#endif + } + + return -1; +} + +__FIT_DECLSPEC +int Thread::kill( int sig ) +{ + // Locker lk( _llock ); + + if ( _id != bad_thread_id ) { +#ifdef __FIT_UITHREADS + return thr_kill( _id, sig ); +#endif +#ifdef _PTHREADS + return pthread_kill( _id, sig ); +#endif +#ifdef __FIT_WIN32THREADS + // The behavior of TerminateThread significant differ from SOLARIS and POSIX + // threads, and I don't find analogs to workaround... + return TerminateThread( _id, sig ) ? 0 : -1; +#endif + } + return -1; +} + +__FIT_DECLSPEC +void Thread::_exit( int code ) +{ +#ifdef _PTHREADS + pthread_exit( reinterpret_cast<ret_t>(code) ); +#endif +#ifdef __FIT_UITHREADS + thr_exit( reinterpret_cast<ret_t>(code) ); +#endif +#ifdef __FIT_WIN32THREADS + ExitThread( code ); +#endif +} + +#ifdef __FIT_UITHREADS +__FIT_DECLSPEC +int Thread::join_all() +{ + while ( thr_join( 0, 0, 0 ) == 0 ) ; + + return 0; +} +#endif + +__FIT_DECLSPEC +void Thread::signal_exit( int sig ) +{ +#ifdef _PTHREADS + _uw_alloc_type *user_words = + static_cast<_uw_alloc_type *>(pthread_getspecific( Thread::_mt_key )); + if ( user_words == 0 ) { + // async signal unsafe? or wrong thread called? + // this a bad point, do nothing + return; + } + user_words += Thread::_self_idx; + Thread *me = reinterpret_cast<Thread *>(*reinterpret_cast<void **>(user_words)); + // _STLP_ASSERT( me->is_self() ); + + // follow part of _call + if ( (me->_flags & (daemon | detached)) != 0 ) { // otherwise join expected + // scoped_lock lk( _rip_id_lock ); // !!!!??? in the signal handler? + me->_rip_id = me->_id = bad_thread_id; + } else { + me->_id = bad_thread_id; + } + me->_dealloc_uw(); // clear user words + void *_param = me->_param; + size_t _param_sz = me->_param_sz; + try { + if ( _param_sz > sizeof(void *) ) { // that's allocated + delete [] __STATIC_CAST(char *,_param); + _param_sz = 0; + _param = 0; + } + } + catch ( ... ) { + } +#endif + // well, this is suspicious, due to pthread_exit isn't async signal + // safe; what I should use here? + Thread::_exit( 0 ); +} + +__FIT_DECLSPEC +void block_signal( int sig ) +{ +#ifdef __unix + sigset_t sigset; + + sigemptyset( &sigset ); + sigaddset( &sigset, sig ); +# ifdef __FIT_UITHREADS + thr_sigsetmask( SIG_BLOCK, &sigset, 0 ); +# endif +# ifdef _PTHREADS + pthread_sigmask( SIG_BLOCK, &sigset, 0 ); +# endif +#endif // __unix +} + +__FIT_DECLSPEC +void unblock_signal( int sig ) +{ +#ifdef __unix + sigset_t sigset; + + sigemptyset( &sigset ); + sigaddset( &sigset, sig ); +# ifdef __FIT_UITHREADS + thr_sigsetmask( SIG_UNBLOCK, &sigset, 0 ); +# endif +# ifdef _PTHREADS + pthread_sigmask( SIG_UNBLOCK, &sigset, 0 ); +# endif +#endif // __unix +} + +__FIT_DECLSPEC +int signal_handler( int sig, SIG_PF handler ) +{ +#ifdef __unix // catch SIGPIPE here + struct sigaction act; + + sigemptyset( &act.sa_mask ); + sigaddset( &act.sa_mask, sig ); + + act.sa_flags = 0; // SA_RESTART; + act.sa_handler = handler; + return sigaction( sig, &act, 0 ); +#else + return -1; +#endif // __unix +} + +__FIT_DECLSPEC +int signal_handler( int sig, siginfo_handler_type handler ) +{ +#ifdef __unix // catch SIGPIPE here + struct sigaction act; + + sigemptyset( &act.sa_mask ); + sigaddset( &act.sa_mask, sig ); + + act.sa_flags = SA_SIGINFO; // SA_RESTART; + act.sa_sigaction = handler; + return sigaction( sig, &act, 0 ); +#else + return -1; +#endif // __unix +} + +__FIT_DECLSPEC +void fork() throw( fork_in_parent, std::runtime_error ) +{ +#ifdef __unix + // MT_REENTRANT( detail::_F_lock, _1 ); + fork_in_parent f( ::fork() ); + if ( f.pid() > 0 ) { + throw f; + } + if ( f.pid() == -1 ) { + throw std::runtime_error( msg2 ); + } + detail::_ppid = detail::_pid; + detail::_pid = syscall( SYS_getpid ); +#endif +} + +__FIT_DECLSPEC +void become_daemon() throw( fork_in_parent, std::runtime_error ) +{ +#ifdef __unix + try { + xmt::fork(); + + chdir( "/var/tmp" ); // for CWD: if not done, process remain with same WD + // and don't allow unmount volume, for example + ::setsid(); // become session leader + ::close( 0 ); // close stdin + ::close( 1 ); // close stdout + ::close( 2 ); // close stderr + // This is broken in some versions of glibc (Linux): + ::open( "/dev/null", O_RDONLY, 0 ); // redirect stdin from /dev/null + ::open( "/dev/null", O_WRONLY, 0 ); // redirect stdout to /dev/null + ::open( "/dev/null", O_WRONLY, 0 ); // redirect stderr to /dev/null + } + catch ( fork_in_parent& ) { + throw; + } + catch ( std::runtime_error& ) { + throw; + } +#endif +} + +// #ifdef __GNUC__ +// void Thread::_create( const void *p, size_t psz ) +// #else +void Thread::_create( const void *p, size_t psz ) throw(std::runtime_error) +// #endif +{ + if ( psz > sizeof(void *) ) { // can't pass on pointer + // Hey, deallocation SHOULD be either in this method, or in _call ONLY, + // and never more! + _param = new char [psz]; +#ifdef WIN32 + memcpy( _param, p, psz ); +#else + std::memcpy( _param, p, psz ); +#endif + } else { + _param = const_cast<void *>(p); + } + _param_sz = psz; + + int err = 0; +#ifdef __FIT_CREATE_THREAD_STACK_INFO + // _stack_on_create + { + std::stringstream s; + callstack( s ); + _stack_on_create = s.str(); + } +#endif + +#ifdef _PTHREADS + pthread_attr_t attr; + if ( _flags != 0 || _stack_sz != 0 ) { + pthread_attr_init( &attr ); // pthread_attr_create --- HP-UX 10.20 + // pthread_attr_setstacksize( &attr, 0x80000 ); // min 0x50000 + if ( _flags & bound ) { + pthread_attr_setscope( &attr, bound ); // PTHREAD_SCOPE_PROCESS + } + if ( _flags & detached ) { // the same as daemon: detached == daemon for POSIX + pthread_attr_setdetachstate( &attr, detached ); // PTHREAD_CREATE_DETACHED + } + if ( _stack_sz != 0 ) { + _stack_sz = std::max( static_cast<size_t>(PTHREAD_STACK_MIN), _stack_sz ); + pthread_attr_setstacksize( &attr, _stack_sz /* PTHREAD_STACK_MIN * 2 */ ); + } + // pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED ); + // pthread_attr_setschedpolicy(&attr,SCHED_OTHER); + } + scoped_lock lk( _rip_id_lock ); + err = pthread_create( &_id, _flags != 0 || _stack_sz != 0 ? &attr : 0, _call, this ); + if ( err != 0 ) { + _rip_id = _id = bad_thread_id; + } else { + _rip_id = _id; + } + lk.unlock(); + if ( _flags != 0 || _stack_sz != 0 ) { + pthread_attr_destroy( &attr ); + } +#endif +#ifdef __FIT_UITHREADS + err = thr_create( 0, 0, _call, this, _flags, &_id ); +#endif +#ifdef __FIT_WIN32THREADS + _rip_id = _id = CreateThread( 0, 0, _call, this, (_flags & suspended), &_thr_id ); + err = GetLastError(); +#endif + + if ( err != 0 ) { + if ( psz > sizeof(void *) ) { // clear allocated here + delete [] __STATIC_CAST(char *,_param); + } + std::stringstream s; + s << msg1 << " error " << err << endl; + throw std::runtime_error( s.str() ); + } +} + +#ifdef _WIN32 +#pragma warning( disable : 4101 ) +#endif + +#ifdef __unix +void *Thread::_call( void *p ) +#endif +#ifdef WIN32 +unsigned long __stdcall Thread::_call( void *p ) +#endif +{ + Thread *me = static_cast<Thread *>(p); + + // After exit of me->_entrance, there is may be no more *me itself, + // so it's members may be unaccessible. Don't use me->"*" after call + // of me->_entrance!!! + void *_param = me->_param; + size_t _param_sz = me->_param_sz; + ret_t ret = 0; + +//#ifdef _PTHREADS +//# ifndef __hpux +// if ( me->_flags & (daemon | detached) ) { +// pthread_detach( me->_id ); +// } +//# endif +//#endif + +#ifdef WIN32 + set_unexpected( unexpected ); + set_terminate( terminate ); +#else +# ifndef __FIT_NETWARE + std::set_unexpected( Thread::unexpected ); + std::set_terminate( Thread::terminate ); +# endif // !__FIT_NETWARE +#endif + + me->pword( _self_idx ) = me; // to have chance make Thread sanity by signal + // In most cases for Linux there are problems with signals processing, + // so I don't set it default more + // signal_handler( SIGTERM, signal_exit ); // set handler for sanity + try { + ret = me->_entrance( _param ); + + // I should make me->_id = bad_thread_id; here... + // This is in conflict what I say in the begin of this function. + // So don't delete Thread before it termination! + + if ( (me->_flags & (daemon | detached)) != 0 ) { // otherwise join expected + // Locker lk( me->_llock ); +#ifdef __FIT_WIN32THREADS + CloseHandle( me->_id ); +#endif + scoped_lock lk( me->_rip_id_lock ); + me->_id = bad_thread_id; + me->_rip_id = bad_thread_id; + } else { + // Locker lk( me->_llock ); + me->_id = bad_thread_id; + } + me->_dealloc_uw(); // free user words + } + catch ( std::exception& e ) { + if ( (me->_flags & (daemon | detached)) != 0 ) { // otherwise join expected + // Locker lk( me->_llock ); +#ifdef __FIT_WIN32THREADS + CloseHandle( me->_id ); +#endif + scoped_lock lk( me->_rip_id_lock ); + me->_id = bad_thread_id; + me->_rip_id = bad_thread_id; + } else { + // Locker lk( me->_llock ); + me->_id = bad_thread_id; + } + me->_dealloc_uw(); // free user words +#ifndef _WIN32 + cerr << e.what() << endl; +#endif + ret = reinterpret_cast<ret_t>(-1); + } + catch ( int sig ) { + if ( (me->_flags & (daemon | detached)) != 0 ) { // otherwise join expected + // Locker lk( me->_llock ); +#ifdef __FIT_WIN32THREADS + CloseHandle( me->_id ); +#endif + scoped_lock lk( me->_rip_id_lock ); + me->_id = bad_thread_id; + me->_rip_id = bad_thread_id; + } else { + // Locker lk( me->_llock ); + me->_id = bad_thread_id; + } + + me->_dealloc_uw(); // free user words + // const char *_sig_ = strsignal( sig ); +#ifndef _WIN32 + cerr << "\n--- Thread: signal " << sig /* (_sig_ ? _sig_ : "unknown") */ << " detected ---" << endl; +#endif + ret = reinterpret_cast<ret_t>(sig); + } + catch ( ... ) { + if ( (me->_flags & (daemon | detached)) != 0 ) { // otherwise join expected + // Locker lk( me->_llock ); +#ifdef __FIT_WIN32THREADS + CloseHandle( me->_id ); +#endif + scoped_lock lk( me->_rip_id_lock ); + me->_id = bad_thread_id; + me->_rip_id = bad_thread_id; + } else { + // Locker lk( me->_llock ); + me->_id = bad_thread_id; + } + me->_dealloc_uw(); // free user words +#ifndef _WIN32 + cerr << "\n--- Thread: unknown exception occur ---" << endl; +#endif + ret = reinterpret_cast<ret_t>(-1); + } + + try { + if ( _param_sz > sizeof(void *) ) { // that's allocated + delete [] __STATIC_CAST(char *,_param); + _param_sz = 0; + _param = 0; + } + } + catch ( ... ) { + ret = reinterpret_cast<ret_t>(-1); + } + +#if defined( __SUNPRO_CC ) && defined( __i386 ) + Thread::_exit( ret ); +#endif + + return ret; +} +#ifdef _WIN32 +#pragma warning( default : 4101 ) +#endif + +void Thread::unexpected() +{ +#ifndef _WIN32 + cerr << "\nUnexpected exception, catched here: " << __FILE__ << ':' << __LINE__ << endl; +#endif + signal_exit( SIGTERM ); // Thread::_exit( 0 ); +} + +void Thread::terminate() +{ +#ifndef _WIN32 + cerr << "\nTerminate exception, catched here: " << __FILE__ << ':' << __LINE__<< endl; +#endif + signal_exit( SIGTERM ); // Thread::_exit( 0 ); +} + +int Thread::xalloc() +{ + scoped_lock _l( _idx_lock ); + return _idx++; +} + +pid_t getpid() +{ + return detail::_pid; +} + +pid_t getppid() +{ + return detail::_ppid; +} + +} // namespace xmt This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-02-11 17:38:18
|
Revision: 1812 http://complement.svn.sourceforge.net/complement/?rev=1812&view=rev Author: complement Date: 2008-02-11 09:38:15 -0800 (Mon, 11 Feb 2008) Log Message: ----------- base for branch, conversion mt -> wg21 working draft Added Paths: ----------- branches/wg21-thread/include/mt/mutex Copied: branches/wg21-thread/include/mt/mutex (from rev 1811, branches/wg21-thread/include/mt/xmt.h) =================================================================== --- branches/wg21-thread/include/mt/mutex (rev 0) +++ branches/wg21-thread/include/mt/mutex 2008-02-11 17:38:15 UTC (rev 1812) @@ -0,0 +1,1760 @@ +// -*- C++ -*- Time-stamp: <07/09/15 10:03:40 ptr> + +/* + * Copyright (c) 1997-1999, 2002-2007 + * Petr Ovtchenkov + * + * Portion Copyright (c) 1999-2001 + * Parallel Graphics Ltd. + * + * Licensed under the Academic Free License version 3.0 + * + */ + +#ifndef __XMT_H +#define __XMT_H + +#ifndef __config_feature_h +#include <config/feature.h> +#endif + +#include <memory> +#include <cstddef> +#include <stdexcept> + +#if !defined(_STLPORT_VERSION) && !defined(__STATIC_CAST) +# define __STATIC_CAST(t,v) static_cast<t>(v) +#endif + +#ifdef WIN32 +# include <windows.h> +# include <memory> +# include <limits> +# define ETIME 62 /* timer expired */ +# pragma warning( disable : 4290) +#endif // WIN32 + +#ifdef __unix +# if defined( _REENTRANT ) && !defined(_NOTHREADS) +# ifdef _PTHREADS +# include <pthread.h> +# include <semaphore.h> +# include <sched.h> +# else +# include <thread.h> +# include <synch.h> +# endif +# elif !defined(_NOTHREADS) // !_REENTRANT +# define _NOTHREADS +# endif +// # define __DLLEXPORT +#endif // __unix + +#include <cerrno> + +#include <mt/time.h> + +#ifdef _REENTRANT + +# define MT_REENTRANT(point,nm) xmt::scoped_lock nm(point) +# define MT_LOCK(point) point.lock() +# define MT_UNLOCK(point) point.unlock() + +#else // !_REENTRANT + +# define MT_REENTRANT(point,nm) ((void)0) +# define MT_REENTRANT_RS(point,nm) ((void)0) +# define MT_LOCK(point) ((void)0) +# define MT_UNLOCK(point) ((void)0) + +#endif // _REENTRANT + +#include <signal.h> + +extern "C" { + +#ifndef SIG_PF // sys/signal.h + +# ifdef WIN32 +typedef void __cdecl SIG_FUNC_TYP(int); +# else +typedef void SIG_FUNC_TYP(int); +# endif +typedef SIG_FUNC_TYP *SIG_TYP; +# define SIG_PF SIG_TYP + +# ifndef SIG_DFL +# define SIG_DFL (SIG_PF)0 +# endif +# ifndef SIG_ERR +# define SIG_ERR (SIG_PF)-1 +# endif +# ifndef SIG_IGN +# define SIG_IGN (SIG_PF)1 +# endif +# ifndef SIG_HOLD +# define SIG_HOLD (SIG_PF)2 +# endif +#endif // SIG_PF + +typedef void siginfo_handler_type( int, siginfo_t *, void * ); + +} // extern "C" + +namespace xmt { + + +// Exceptions + +// class thread_exit; +// class thread_cancel: public thread_exit; +// class thread_error: public exception; + +class lock_error : + public std::exception +{ + private: + int r_; + + public: + + explicit lock_error( int r ) : + r_( r ) + { } + + virtual char const *what() throw() + { return "std::lock_error"; } + + int error() const + { return r_; } +}; + +namespace detail { + +#ifdef __FIT_PSHARED_MUTEX +extern std::string _notpshared; +#endif + +#ifdef __FIT_XSI_THR +extern std::string _notrecursive; +#endif + +} // namespace detail + +// extern __FIT_DECLSPEC void signal_throw( int sig ) throw( int ); +// extern __FIT_DECLSPEC void signal_thread_exit( int sig ); + +// #ifdef __unix +// extern "C" void *_xcall( void * ); // forward declaration +// #endif +// #ifdef WIN32 +// extern "C" unsigned long __stdcall _xcall( void *p ); // forward declaration +// #endif + +#ifndef WIN32 +// using std::size_t; +#endif +#ifdef __GNUC__ + // using std::runtime_error; +#else +using std::runtime_error; +#endif + +#ifndef _WIN32 +class fork_in_parent : + public std::exception +{ + public: + fork_in_parent() throw() + { _pid = 0; } + fork_in_parent( pid_t p ) throw() + { _pid = p; } + virtual ~fork_in_parent() throw() + { } + virtual const char *what() const throw() + { return "class fork_in_parent"; } + pid_t pid() throw() + { return _pid; } + + private: + pid_t _pid; +}; +#endif // !_WIN32 + + +template <bool SCOPE> class __condition; + +// if parameter SCOPE (process scope) true, PTHREAD_PROCESS_SHARED will +// be used; otherwise PTHREAD_PROCESS_PRIVATE. +// Of cause, system must support process scope... +// Linux at 2003-01-19 NOT SUPPORT PTHREAD_PROCESS_SHARED mutex! +// And Windows too! +// +template <bool RECURSIVE_SAFE, bool SCOPE> +class __mutex_base +{ + public: + __mutex_base() + { +#ifdef _PTHREADS + if ( SCOPE || RECURSIVE_SAFE ) { + pthread_mutexattr_t att; + pthread_mutexattr_init( &att ); +# ifdef __FIT_PSHARED_MUTEX + if ( SCOPE ) { + if ( pthread_mutexattr_setpshared( &att, PTHREAD_PROCESS_SHARED ) != 0 ) { + throw std::invalid_argument( detail::_notpshared ); + } + } +# endif // __FIT_PSHARED_MUTEX +# ifdef __FIT_XSI_THR // Unix 98 or X/Open System Interfaces Extention + if ( RECURSIVE_SAFE ) { + if ( pthread_mutexattr_settype( &att, PTHREAD_MUTEX_RECURSIVE ) != 0 ) { + throw std::invalid_argument( detail::_notrecursive ); + } + } +# endif + pthread_mutex_init( &_M_lock, &att ); + pthread_mutexattr_destroy( &att ); + } else { + pthread_mutex_init( &_M_lock, 0 ); + } +#endif // _PTHREADS +#ifdef __FIT_UITHREADS + if ( SCOPE ) { + // or USYNC_PROCESS_ROBUST to detect already initialized mutex + // in process scope + mutex_init( &_M_lock, USYNC_PROCESS, 0 ); + } else { + mutex_init( &_M_lock, 0, 0 ); + } +#endif +#ifdef __FIT_WIN32THREADS + InitializeCriticalSection( &_M_lock ); +#endif + } + + ~__mutex_base() + { +#ifdef _PTHREADS + pthread_mutex_destroy( &_M_lock ); +#endif +#ifdef __FIT_UITHREADS + mutex_destroy( &_M_lock ); +#endif +#ifdef WIN32 + DeleteCriticalSection( &_M_lock ); +#endif + } + + private: + __mutex_base( const __mutex_base& ) + { } + + protected: +#ifdef _PTHREADS + pthread_mutex_t _M_lock; +#endif +#ifdef __FIT_UITHREADS + mutex_t _M_lock; +#endif +#ifdef __FIT_WIN32THREADS + CRITICAL_SECTION _M_lock; +#endif + +#ifndef __FIT_WIN32THREADS + private: + friend class __condition<SCOPE>; +#endif +}; + +#ifdef __FIT_PTHREAD_SPINLOCK + +// The IEEE Std. 1003.1j-2000 introduces functions to implement spinlocks. +template <bool SCOPE> +class __spinlock_base +{ + public: + __spinlock_base() + { +#ifdef _PTHREADS + pthread_spin_init( &_M_lock, SCOPE ? 1 : 0 ); +#endif // _PTHREADS + } + + ~__spinlock_base() + { +#ifdef _PTHREADS + pthread_spin_destroy( &_M_lock ); +#endif + } + protected: +#ifdef _PTHREADS + pthread_spinlock_t _M_lock; +#endif +}; + +#endif // __FIT_PTHREAD_SPINLOCK + +// Portable mutex implementation. If the parameter RECURSIVE_SAFE +// is true, mutex will be recursive safe (detect deadlock). +// If RECURSIVE_SAFE is false, implementation may not to be +// recursive-safe. +// The SCOPE parameter designate mutex scope---shared between +// processes (true), or only inside threads of one process (false). +// Note, that not all OS support interprocess mutex scope +// (for example, Windows and Linux). +template <bool RECURSIVE_SAFE, bool SCOPE> +class __mutex : + public __mutex_base<RECURSIVE_SAFE,SCOPE> +{ + public: + __mutex() + { } + + ~__mutex() + { } + + void lock() + { +#ifdef _PTHREADS + pthread_mutex_lock( &this->_M_lock ); +#endif +#ifdef __FIT_UITHREADS + mutex_lock( &this->_M_lock ); +#endif +#ifdef __FIT_WIN32THREADS + EnterCriticalSection( &this->_M_lock ); +#endif + } + +#if !defined( WIN32 ) || (defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400) + int try_lock() + { +#ifdef _PTHREADS + return pthread_mutex_trylock( &this->_M_lock ); +#endif +#ifdef __FIT_UITHREADS + return mutex_trylock( &this->_M_lock ); +#endif +#ifdef __FIT_WIN32THREADS + return TryEnterCriticalSection( &this->_M_lock ) != 0 ? 0 : -1; +#endif +#ifdef _NOTHREADS + return 0; +#endif + } +#endif // !WIN32 || _WIN32_WINNT >= 0x0400 + + void unlock() + { +#ifdef _PTHREADS + pthread_mutex_unlock( &this->_M_lock ); +#endif +#ifdef __FIT_UITHREADS + mutex_unlock( &this->_M_lock ); +#endif +#ifdef __FIT_WIN32THREADS + LeaveCriticalSection( &this->_M_lock ); +#endif + } + + private: + __mutex( const __mutex& ) + { } + +#ifndef __FIT_WIN32THREADS + private: + friend class __condition<SCOPE>; +#endif +}; + +#ifdef __FIT_PTHREAD_SPINLOCK +// Spinlock-based locks (IEEE Std. 1003.1j-2000) + +template <bool RS, bool SCOPE> class __spinlock; + +template <bool SCOPE> +class __spinlock<false,SCOPE> : + public __spinlock_base<SCOPE> +{ + public: + __spinlock() + { } + + ~__spinlock() + { } + + void lock() + { +# ifdef _PTHREADS + pthread_spin_lock( &this->_M_lock ); +# endif + } + + int try_lock() + { +# ifdef _PTHREADS + return pthread_spin_trylock( &this->_M_lock ); +# endif +# ifdef _NOTHREADS + return 0; +# endif + } + + void unlock() + { +# ifdef _PTHREADS + pthread_spin_unlock( &this->_M_lock ); +# endif + } + + private: + __spinlock( const __spinlock& ) + { } + +}; + +template <bool SCOPE> +class __spinlock<true,SCOPE> : // Recursive safe + public __spinlock_base<SCOPE> +{ + public: + __spinlock() + { } + + ~__spinlock() + { } + + void lock() + { +# ifndef _NOTHREADS +# ifdef _PTHREADS + pthread_t _c_id = pthread_self(); +# endif +# ifdef __FIT_UITHREADS + thread_t _c_id = thr_self(); +# endif + if ( _c_id == _id ) { + ++_count; + return; + } +# ifdef _PTHREADS + pthread_spin_lock( &this->_M_lock ); +# endif + _id = _c_id; + _count = 0; +# endif // !_NOTHREADS + } + + int try_lock() + { +# ifdef _NOTHREADS + return 0; +# else // _NOTHREADS +# ifdef _PTHREADS + pthread_t _c_id = pthread_self(); +# endif +# ifdef __FIT_UITHREADS + thread_t _c_id = thr_self(); +# endif + if ( _c_id == _id ) { + ++_count; + return 0; + } +# ifdef _PTHREADS + int res = pthread_spin_trylock( &this->_M_lock ); +# endif + if ( res != 0 ) { + return res; + } + + _id = _c_id; + _count = 0; + + return 0; +# endif // !_NOTHREADS + } + + void unlock() + { +# ifndef _NOTHREADS + if ( --_count == 0 ) { +# ifdef _PTHREADS + _id = __STATIC_CAST(pthread_t,-1); + pthread_spin_unlock( &this->_M_lock ); +# endif +# endif // !_NOTHREADS + } + } + protected: +# ifndef _NOTHREADS + unsigned _count; +# endif // !_NOTHREADS + +# ifdef _PTHREADS + pthread_t _id; +# endif +# ifdef __FIT_UITHREADS + thread_t _id; +# endif + + private: + __spinlock( const __spinlock& ) + { } +}; +#endif // __FIT_PTHREAD_SPINLOCK + +// Recursive Safe mutex. + +// This specialization need for POSIX and DCE threads, +// because Windows CriticalSection is recursive safe. +// By the way, point for enhancement: __UNIX_98 +// (or XSI---X/Open System Interfaces Extention) has recursive mutex option. +// Another specialization? + +#if (defined(__unix) && !defined(__FIT_XSI_THR)) + +// This specialization need for old POSIX and DCE threads, +// before XSI (X/Open System Interfaces Extention) or Unix 98. +// because Windows CriticalSection is recursive safe, and +// XSI implementation has appropriate mutex parameter (see +// __mutex_base above). + +template <bool SCOPE> +class __mutex<true,SCOPE> : // Recursive Safe + public __mutex_base<true,SCOPE> +{ + public: + __mutex() : + _count( 0 ), +# ifdef __FIT_UITHREADS + _id( __STATIC_CAST(thread_t,-1) ) +# endif +# ifdef _PTHREADS + _id( __STATIC_CAST(pthread_t,-1) ) +# endif + { } + + ~__mutex() + { } + + void lock() + { +# ifndef _NOTHREADS +# ifdef _PTHREADS + pthread_t _c_id = pthread_self(); +# endif +# ifdef __FIT_UITHREADS + thread_t _c_id = thr_self(); +# endif + if ( _c_id == _id ) { + ++_count; + return; + } +# ifdef _PTHREADS + pthread_mutex_lock( &_M_lock ); +# endif +# ifdef __FIT_UITHREADS + mutex_lock( &_M_lock ); +# endif + _id = _c_id; + _count = 0; +# endif // !_NOTHREADS + } + + // Equivalent to lock(), except that if the mutex object referenced + // by mutex is currently locked the call return immediately. + // If mutex is currently owned by the calling thread, the mutex lock count + // incremented by one and the try_lock() function immediately return success + // (value 0). Otherwise, if mutex is currently owned by another thread, + // return error (non-zero). + + int try_lock() + { +# ifdef _NOTHREADS + return 0; +# else // _NOTHREADS +# ifdef _PTHREADS + pthread_t _c_id = pthread_self(); +# endif +# ifdef __FIT_UITHREADS + thread_t _c_id = thr_self(); +# endif + if ( _c_id == _id ) { + ++_count; + return 0; + } +# ifdef _PTHREADS + int res = pthread_mutex_trylock( &_M_lock ); +# endif +# ifdef __FIT_UITHREADS + int res = mutex_trylock( &_M_lock ); +# endif + if ( res != 0 ) { + return res; + } + + _id = _c_id; + _count = 0; + + return 0; +# endif // !_NOTHREADS + } + + void unlock() + { +# ifndef _NOTHREADS + if ( --_count == 0 ) { +# ifdef __FIT_UITHREADS + _id = __STATIC_CAST(thread_t,-1); + mutex_unlock( &_M_lock ); +# endif +# ifdef _PTHREADS + _id = __STATIC_CAST(pthread_t,-1); + pthread_mutex_unlock( &_M_lock ); +# endif +# endif // !_NOTHREADS + } + } + + private: + __mutex( const __mutex& ) + { } + + protected: +# ifndef _NOTHREADS + unsigned _count; +# endif // !_NOTHREADS + +# ifdef _PTHREADS + pthread_t _id; +# endif +# ifdef __FIT_UITHREADS + thread_t _id; +# endif +}; +#endif // __unix && !__FIT_XSI_THR + +#ifdef __FIT_RWLOCK +// Read-write mutex: IEEE Std 1003.1, 2001, 2004 Editions + +template <bool SCOPE> +class __rw_mutex_base +{ + public: + __rw_mutex_base() + { +#ifdef _PTHREADS + if ( SCOPE ) { + pthread_rwlockattr_t att; + pthread_rwlockattr_init( &att ); +# ifdef __FIT_PSHARED_MUTEX + if ( pthread_rwlockattr_setpshared( &att, PTHREAD_PROCESS_SHARED ) != 0 ) { + throw std::invalid_argument( xmt::detail::_notpshared ); + } +# endif // __FIT_PSHARED_MUTEX + pthread_rwlock_init( &_M_lock, &att ); + pthread_rwlockattr_destroy( &att ); + } else { + pthread_rwlock_init( &_M_lock, 0 ); + } +#endif // _PTHREADS +#ifdef __FIT_UITHREADS +#error Fix me! + if ( SCOPE ) { + // or USYNC_PROCESS_ROBUST to detect already initialized mutex + // in process scope + mutex_init( &_M_lock, USYNC_PROCESS, 0 ); + } else { + mutex_init( &_M_lock, 0, 0 ); + } +#endif +#ifdef __FIT_WIN32THREADS +#error Fix me! + InitializeCriticalSection( &_M_lock ); +#endif + } + + ~__rw_mutex_base() + { +#ifdef _PTHREADS + pthread_rwlock_destroy( &_M_lock ); +#endif +#ifdef __FIT_UITHREADS +#error Fix me! + mutex_destroy( &_M_lock ); +#endif +#ifdef WIN32 +#error Fix me! + DeleteCriticalSection( &_M_lock ); +#endif + } + + private: + __rw_mutex_base( const __rw_mutex_base& ) + { } + + protected: +#ifdef _PTHREADS + pthread_rwlock_t _M_lock; +#endif +#ifdef __FIT_UITHREADS +#error Fix me! + mutex_t _M_lock; +#endif +#ifdef __FIT_WIN32THREADS +#error Fix me! + CRITICAL_SECTION _M_lock; +#endif +}; + +template <bool SCOPE> +class __rw_mutex : + public __rw_mutex_base<SCOPE> +{ + public: + __rw_mutex() + { } + + ~__rw_mutex() + { } + + void rdlock() + { +#ifdef _PTHREADS + pthread_rwlock_rdlock( &this->_M_lock ); +#endif +#ifdef __FIT_UITHREADS +#error Fix me! + mutex_lock( &this->_M_lock ); +#endif +#ifdef __FIT_WIN32THREADS +#error Fix me! + EnterCriticalSection( &this->_M_lock ); +#endif + } + + void lock() + { +#ifdef _PTHREADS + pthread_rwlock_wrlock( &this->_M_lock ); +#endif +#ifdef __FIT_UITHREADS +#error Fix me! + mutex_lock( &this->_M_lock ); +#endif +#ifdef __FIT_WIN32THREADS +#error Fix me! + EnterCriticalSection( &this->_M_lock ); +#endif + } + +#if !defined( WIN32 ) || (defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400) + int try_rdlock() + { +#ifdef _PTHREADS + return pthread_rwlock_tryrdlock( &this->_M_lock ); +#endif +#ifdef __FIT_UITHREADS +#error Fix me! + return mutex_trylock( &this->_M_lock ); +#endif +#ifdef __FIT_WIN32THREADS +#error Fix me! + return TryEnterCriticalSection( &this->_M_lock ) != 0 ? 0 : -1; +#endif +#ifdef _NOTHREADS +#error Fix me! + return 0; +#endif + } + + int try_lock() + { +#ifdef _PTHREADS + return pthread_rwlock_trywrlock( &this->_M_lock ); +#endif +#ifdef __FIT_UITHREADS +#error Fix me! + return mutex_trylock( &this->_M_lock ); +#endif +#ifdef __FIT_WIN32THREADS +#error Fix me! + return TryEnterCriticalSection( &this->_M_lock ) != 0 ? 0 : -1; +#endif +#ifdef _NOTHREADS +#error Fix me! + return 0; +#endif + } + +#endif // !WIN32 || _WIN32_WINNT >= 0x0400 + + void unlock() + { +#ifdef _PTHREADS + pthread_rwlock_unlock( &this->_M_lock ); +#endif +#ifdef __FIT_UITHREADS +#error Fix me! + mutex_unlock( &this->_M_lock ); +#endif +#ifdef __FIT_WIN32THREADS +#error Fix me! + LeaveCriticalSection( &this->_M_lock ); +#endif + } + + private: + __rw_mutex( const __rw_mutex& ) + { } +}; + +#endif // __FIT_RWLOCK + +template <class M> +class basic_lock +{ + public: + basic_lock( const M& point, bool initially_locked = true ) : + m( point ), + lk( false ) + { if ( initially_locked ) lock(); } + ~basic_lock() + { if ( lk ) const_cast<M&>(m).unlock(); } + + void lock() + { + if ( lk ) { + throw lock_error( 0 ); + } + const_cast<M&>(m).lock(); + lk = true; + } + + void unlock() + { + if ( !lk ) { + throw lock_error( 0 ); + } + lk = false; + const_cast<M&>(m).unlock(); + } + + private: + basic_lock( const basic_lock& ) + { } + basic_lock& operator =( const basic_lock& ) + { return *this; } + + const M& m; + bool lk; +}; + +#ifdef __FIT_RWLOCK +template <class M> +class basic_read_lock +{ + public: + basic_read_lock( const M& point, bool initially_locked = true ) : + m( point ), + lk( false ) + { if ( initially_locked ) lock(); } + ~basic_read_lock() + { if ( lk ) const_cast<M&>(m).unlock(); } + + void lock() + { + if ( lk ) { + throw lock_error( 0 ); + } + const_cast<M&>(m).rdlock(); + lk = true; + } + + void unlock() + { + if ( !lk ) { + throw lock_error( 0 ); + } + lk = false; + const_cast<M&>(m).unlock(); + } + + private: + basic_read_lock( const basic_read_lock& ) + { } + basic_read_lock& operator =( const basic_read_lock& ) + { return *this; } + + const M& m; + bool lk; +}; +#endif // __FIT_RWLOCK + +typedef __mutex<false,false> mutex; +typedef __mutex<true,false> recursive_mutex; +typedef __mutex<false,true> shared_mutex; +typedef __mutex<true,true> shared_recursive_mutex; +#ifdef __FIT_RWLOCK +typedef __rw_mutex<false> rw_mutex; +#endif // __FIT_RWLOCK +#ifdef __FIT_PTHREAD_SPINLOCK +typedef __spinlock<false,false> spinlock; +typedef __spinlock<true,false> recursive_spinlock; +#endif // __FIT_RWLOCK + +typedef basic_lock<mutex> scoped_lock; +typedef basic_lock<recursive_mutex> recursive_scoped_lock; +#ifdef __FIT_RWLOCK +typedef basic_read_lock<__rw_mutex<false> > rd_scoped_lock; +typedef basic_lock<__rw_mutex<false> > wr_scoped_lock; +#endif // __FIT_RWLOCK +#ifdef __FIT_PTHREAD_SPINLOCK +typedef basic_lock<spinlock> spin_scoped_lock; +typedef basic_lock<recursive_spinlock> recursive_spin_scoped_lock; +#endif // __FIT_RWLOCK + +class native_scoped_lock +{ + public: +#ifdef _PTHREADS + explicit native_scoped_lock( const pthread_mutex_t& m ) : +#endif +#ifdef __FIT_UITHREADS + explicit native_scoped_lock( const mutex_t& m ) : +#endif +#ifdef __FIT_WIN32THREADS + explicit native_scoped_lock( const CRITICAL_SECTION& m ) : +#endif + _M_lock( m ) + { +#ifdef _PTHREADS + pthread_mutex_lock( const_cast<pthread_mutex_t *>(&_M_lock) ); +#endif +#ifdef __FIT_UITHREADS + mutex_lock( const_cast<mutex_t *>(&_M_lock) ); +#endif +#ifdef __FIT_WIN32THREADS + EnterCriticalSection( const_cast<CRITICAL_SECTION *>(&_M_lock) ); +#endif + } + + ~native_scoped_lock() + { +#ifdef _PTHREADS + pthread_mutex_unlock( const_cast<pthread_mutex_t *>(&_M_lock) ); +#endif +#ifdef __FIT_UITHREADS + mutex_unlock( const_cast<mutex_t *>(&_M_lock) ); +#endif +#ifdef __FIT_WIN32THREADS + LeaveCriticalSection( const_cast<CRITICAL_SECTION *>(&_M_lock) ); +#endif + } + + private: + native_scoped_lock( const native_scoped_lock& m ) : + _M_lock( m._M_lock ) + { } +#ifdef _PTHREADS + const pthread_mutex_t& _M_lock; +#endif +#ifdef __FIT_UITHREADS + const mutex_t& _M_lock; +#endif +#ifdef __FIT_WIN32THREADS + const CRITICAL_SECTION& _M_lock; +#endif +}; + +template <bool SCOPE> +class __condition +{ + public: + __condition() : + _val( true ) + { +#ifdef __FIT_WIN32THREADS + _cond = CreateEvent( 0, TRUE, TRUE, 0 ); +#endif +#ifdef _PTHREADS + if ( SCOPE ) { + pthread_condattr_t attr; + pthread_condattr_init( &attr ); + pthread_condattr_setpshared( &attr, PTHREAD_PROCESS_SHARED ); + pthread_cond_init( &_cond, &attr ); + pthread_condattr_destroy( &attr ); + } else { + pthread_cond_init( &_cond, 0 ); + } +#endif +#ifdef __FIT_UITHREADS + cond_init( &_cond, 0, 0 ); +#endif + } + + ~__condition() + { +#ifdef __FIT_WIN32THREADS + CloseHandle( _cond ); +#endif +#ifdef _PTHREADS + pthread_cond_destroy( &_cond ); +#endif +#ifdef __FIT_UITHREADS + cond_destroy( &_cond ); +#endif + } + + bool set( bool __v, bool _broadcast = false ) + { + basic_lock<__mutex<false,SCOPE> > _x1( _lock ); + + bool tmp = _val; + _val = __v; +#ifdef __FIT_WIN32THREADS + if ( __v == true && tmp == false ) { + SetEvent( _cond ); + } else if ( __v == false && tmp == true ) { + ResetEvent( _cond ); + } +#endif +#ifdef __FIT_UITHREADS + if ( __v == true && tmp == false ) { + if ( _broadcast ) { + cond_broadcast( &_cond ); + } else { + cond_signal( &_cond ); + } + } +#endif +#ifdef _PTHREADS + if ( __v == true && tmp == false ) { + if ( _broadcast ) { + pthread_cond_broadcast( &_cond ); + } else { + pthread_cond_signal( &_cond ); + } + } +#endif + return tmp; + } + + bool set() const + { return _val; } + + int try_wait() + { + basic_lock<__mutex<false,SCOPE> > _x1( _lock ); + + if ( _val == false ) { +#ifdef __FIT_WIN32THREADS + _x1.unlock(); + if ( WaitForSingleObject( _cond, -1 ) == WAIT_FAILED ) { + return -1; + } + return 0; +#endif +#if defined(__FIT_UITHREADS) || defined(_PTHREADS) + int ret = 0; + while ( !_val ) { + ret = +#ifdef _PTHREADS + pthread_cond_wait( &_cond, &_lock._M_lock ); +#endif +#ifdef __FIT_UITHREADS + cond_wait( &_cond, &_lock._M_lock ); +#endif + } + return ret; +#endif + } + + return 0; + } + + int wait() + { + basic_lock<__mutex<false,SCOPE> > lk( _lock ); + _val = false; + +#ifdef __FIT_WIN32THREADS + ResetEvent( _cond ); + lk.unlock(); + if ( WaitForSingleObject( _cond, -1 ) == WAIT_FAILED ) { + return -1; + } + return 0; +#endif +#if defined(_PTHREADS) || defined(__FIT_UITHREADS) + int ret; + while ( !_val ) { + ret = +#ifdef _PTHREADS + pthread_cond_wait( &_cond, &_lock._M_lock ); +#endif +#ifdef __FIT_UITHREADS + cond_wait( &_cond, &_lock._M_lock ); +#endif + } + + return ret; +#endif +#ifdef _NOTHREADS + return 0; +#endif + } + + int wait_time( const ::timespec *abstime ); + int wait_time( const ::timespec& abstime ) + { return wait_time( &abstime ); } + + int wait_delay( const ::timespec *abstime ); + int wait_delay( const ::timespec& abstime ) + { return wait_time( &abstime ); } + + int try_wait_time( const ::timespec *abstime ); + int try_wait_time( const ::timespec& abstime ) + { return try_wait_time( &abstime ); } + + int try_wait_delay( const ::timespec *abstime ); + int try_wait_delay( const ::timespec& abstime ) + { return try_wait_delay( &abstime ); } + + int signal( bool _broadcast = false ) + { + basic_lock<__mutex<false,SCOPE> > _x1( _lock ); + + _val = true; +#ifdef __FIT_WIN32THREADS + return SetEvent( _cond ) == FALSE ? -1 : 0; +#endif +#ifdef _PTHREADS + return _broadcast ? pthread_cond_broadcast( &_cond ) : pthread_cond_signal( &_cond ); +#endif +#ifdef __FIT_UITHREADS + return _broadcast ? cond_broadcast( &_cond ) : cond_signal( &_cond ); +#endif +#ifdef _NOTHREADS + return 0; +#endif + } + + protected: +#ifdef __FIT_WIN32THREADS + HANDLE _cond; +#endif +#ifdef _PTHREADS + pthread_cond_t _cond; +#endif +#ifdef __FIT_UITHREADS + cond_t _cond; +#endif + __mutex<false,SCOPE> _lock; + bool _val; + + private: + __condition( const __condition& ) + { } +}; + +typedef __condition<false> condition; + +template <bool SCOPE> +class __semaphore +{ + public: + __semaphore( int cnt = 1 ) + { +#ifdef __FIT_WIN32THREADS + _sem = CreateSemaphore( NULL, cnt, INT_MAX, 0 ); // check! + _cnt = cnt; +#endif +#ifdef __FIT_UITHREADS + sema_init( &_sem, cnt, SCOPE ? USYNC_PROCESS : USYNC_THREAD, 0 ); +#endif +#ifdef _PTHREADS + sem_init( &_sem, SCOPE ? 1 : 0, cnt ); +#endif + } + + ~__semaphore() + { +#ifdef __FIT_WIN32THREADS + CloseHandle( _sem ); +#endif +#ifdef __FIT_UITHREADS + sema_destroy( &_sem ); +#endif +#ifdef _PTHREADS + sem_destroy( &_sem ); +#endif + } + + int wait() + { +#ifdef __FIT_WIN32THREADS + --_cnt; + if ( WaitForSingleObject( _sem, -1 ) == WAIT_FAILED ) { + ++_cnt; + return -1; + } + return 0; +#endif +#ifdef __FIT_UITHREADS + return sema_wait( &_sem ); +#endif +#ifdef _PTHREADS + return sem_wait( &_sem ); +#endif + } + + __FIT_DECLSPEC int wait_time( const ::timespec *t ); // wait for time t, or signal + int wait_time( const ::timespec& t ) + { return wait_time( &t ); } + __FIT_DECLSPEC int wait_delay( const ::timespec *t ); // wait, timeout is delay t, or signal + int wait_delay( const ::timespec& t ) + { return wait_delay( &t ); } + + int try_wait() + { +#ifdef __FIT_WIN32THREADS + return _cnt > 0 ? (--_cnt, this->wait()) : -1; +#endif +#ifdef __FIT_UITHREADS + return sema_trywait( &_sem ); +#endif +#ifdef _PTHREADS + return sem_trywait( &_sem ); +#endif + } + + int post() + { +#ifdef __FIT_WIN32THREADS + return ReleaseSemaphore( _sem, 1, &_cnt ) != 0 ? (++_cnt, 0) : -1; +#endif +#ifdef __FIT_UITHREADS + return sema_post( &_sem ); +#endif +#ifdef _PTHREADS + return sem_post( &_sem ); +#endif + } + + int value() + { +#ifdef __FIT_WIN32THREADS + return static_cast<int>(_cnt); +#endif +#ifdef __FIT_UITHREADS +# warning "No semaphore value for Solaris threads!" +#endif +#ifdef _PTHREADS + int v; + int e = sem_getvalue( &_sem, &v ); + + return e == 0 ? v : -1; +#endif + } + + protected: +#ifdef __FIT_WIN32THREADS + HANDLE _sem; + long _cnt; +#endif +#ifdef __FIT_UITHREADS + sema_t _sem; +#endif +#ifdef _PTHREADS + sem_t _sem; +#endif + private: + __semaphore( const __semaphore& ) + { } +}; + +typedef __semaphore<false> semaphore; + +template <bool SCOPE> +int __semaphore<SCOPE>::wait_time( const ::timespec *abstime ) // wait for time t, or signal +{ +#ifdef __FIT_WIN32THREADS + time_t ct = time( 0 ); + time_t _conv = abstime->tv_sec * 1000 + abstime->tv_nsec / 1000000; + + unsigned ms = _conv >= ct ? _conv - ct : 1; + + if ( WaitForSingleObject( _sem, ms ) == WAIT_OBJECT_0 ) { + return 0; + } + return -1; +#endif +#ifdef __FIT_UITHREADS +#warning "Fix me!" +#endif +#ifdef _PTHREADS +# if !(defined(__FreeBSD__) || defined(__OpenBSD__)) + return sem_timedwait( &_sem, abstime ); +# else + return -1; // not implemented +# endif +#endif +} + +template <bool SCOPE> +int __semaphore<SCOPE>::wait_delay( const ::timespec *interval ) // wait, timeout is delay t, or signal +{ +#ifdef __FIT_WIN32THREADS + unsigned ms = interval->tv_sec * 1000 + interval->tv_nsec / 1000000; + + if ( WaitForSingleObject( _sem, ms ) == WAIT_OBJECT_0 ) { + return 0; + } + return -1; +#endif +#ifdef __FIT_UITHREADS +#warning "Fix me!" +#endif +#ifdef _PTHREADS + timespec st; + xmt::gettime( &st ); + st += *interval; +# if !(defined(__FreeBSD__) || defined(__OpenBSD__)) + return sem_timedwait( &_sem, &st ); +# else + return -1; // not implemented +# endif +#endif +} + +template <bool SCOPE> +class __barrier +{ + public: + __barrier( unsigned cnt = 2 ) + { +#ifdef _PTHREADS + pthread_barrierattr_t attr; + pthread_barrierattr_init( &attr ); + pthread_barrierattr_setpshared( &attr, SCOPE ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE ); + pthread_barrier_init( &_barr, &attr, cnt ); + pthread_barrierattr_destroy( &attr ); +#endif + } + + ~__barrier() + { +#ifdef _PTHREADS + pthread_barrier_destroy( &_barr ); +#endif + } + + int wait() + { +#ifdef _PTHREADS + return pthread_barrier_wait( &_barr ); +#endif + } + + private: +#ifdef _PTHREADS + pthread_barrier_t _barr; +#endif +}; + +typedef __barrier<false> barrier; + +__FIT_DECLSPEC void fork() throw( fork_in_parent, std::runtime_error ); +__FIT_DECLSPEC void become_daemon() throw( fork_in_parent, std::runtime_error ); +__FIT_DECLSPEC void block_signal( int sig ); +__FIT_DECLSPEC void unblock_signal( int sig ); +__FIT_DECLSPEC int signal_handler( int sig, SIG_PF ); +__FIT_DECLSPEC int signal_handler( int sig, siginfo_handler_type ); + +class Thread +{ + public: +#ifdef _PTHREADS + typedef void * ret_t; +#endif +#ifdef __FIT_WIN32THREADS + typedef long ret_t; +#endif + + typedef ret_t (*entrance_type)( void * ); +#ifdef __FIT_WIN32THREADS + typedef unsigned long thread_key_type; + typedef HANDLE thread_id_type; + // typedef unsigned long thread_id_type; +#endif +#ifdef _PTHREADS + typedef pthread_key_t thread_key_type; + typedef pthread_t thread_id_type; +#endif +#ifdef __FIT_UITHREADS + typedef thread_key_t thread_key_type; + typedef thread_t thread_id_type; +#endif + + enum { + // thread mode flags +#ifdef __FIT_UITHREADS // __STL_SOLARIS_THREADS + bound = THR_BOUND, + detached = THR_DETACHED, + new_lwp = THR_NEW_LWP, + suspended = THR_SUSPENDED, + daemon = THR_DAEMON, +#endif +#if defined(_PTHREADS) + bound = PTHREAD_SCOPE_SYSTEM, // otherwise, PTHREAD_SCOPE_PROCESS, default + detached = PTHREAD_CREATE_DETACHED,// otherwise, PTHREAD_CREATE_JOINABLE, default + new_lwp = 0, // pthread_setconcurrency( pthread_getconcurrency() + 1 ); + suspended = 0, + daemon = detached, +#endif +#ifdef __FIT_WIN32THREADS + bound = 0, + detached = 0x2, + new_lwp = 0, + suspended = CREATE_SUSPENDED, + daemon = detached, +#endif + // state flags + goodbit = 0x00, + badbit = 0x01 + }; + + class Init + { + public: + Init(); + ~Init(); + private: + static int& _count; + }; + + __FIT_DECLSPEC Thread( unsigned flags = 0 ); + + explicit __FIT_DECLSPEC Thread( entrance_type entrance, const void *p = 0, size_t psz = 0, unsigned flags = 0, size_t stack_sz = 0 ); + + __FIT_DECLSPEC ~Thread(); + + __FIT_DECLSPEC + void launch( entrance_type entrance, const void *p = 0, size_t psz = 0, size_t stack_sz = 0 ); + + __FIT_DECLSPEC ret_t join(); + __FIT_DECLSPEC int suspend(); + __FIT_DECLSPEC int resume(); + __FIT_DECLSPEC int kill( int sig ); +#ifdef __FIT_UITHREADS + static __FIT_DECLSPEC int join_all(); +#endif + static __FIT_DECLSPEC void signal_exit( int sig ); // signal handler +#if defined(_PTHREADS) + static int yield() + { return sched_yield(); } +#endif + + bool good() const + { /* Locker lk( _llock ); */ return (_id != bad_thread_id); } + bool bad() const + { /* Locker lk( _llock ); */ return (_id == bad_thread_id); } + bool is_join_req() const // if true, you can (and should) use join() + { scoped_lock lk( _rip_id_lock ); return (_rip_id != bad_thread_id) && ((_flags & (daemon | detached)) == 0); } + + __FIT_DECLSPEC bool is_self(); + + static __FIT_DECLSPEC int xalloc(); + long& iword( int __idx ) + { + // _STLP_ASSERT( is_self() ); + return *static_cast<long *>(_alloc_uw( __idx )); + } + void*& pword( int __idx ) + { + // _STLP_ASSERT( is_self() ); + return *reinterpret_cast<void **>(_alloc_uw( __idx )); + } + + static thread_key_type mtkey() + { return _mt_key; } + + static const thread_id_type bad_thread_id; + + protected: + static __FIT_DECLSPEC void _exit( int code = 0 ); + + private: + Thread( const Thread& ) + { } + + bool _not_run() const + { /* Locker lk( _llock ); */ return _id == bad_thread_id; } + void _create( const void *p, size_t psz ) throw( std::runtime_error); + + static void *_call( void *p ); +#ifdef WIN32 + statuc unsigned long __stdcall _call( void *p ); +#endif + + static void unexpected(); + static void terminate(); + + // assume that sizeof( long ) >= sizeof( void * ); + // otherwise, #ifdef workaround should be here. + // At present, I don't know such OS. +#if 1 + typedef long _uw_alloc_type; +#endif + typedef std::allocator<_uw_alloc_type> alloc_type; + __FIT_DECLSPEC void _dealloc_uw(); + __FIT_DECLSPEC _uw_alloc_type *_alloc_uw( int __idx ); + + static alloc_type alloc; + static int _idx; // user words index + static int _self_idx; // user words index, that word point to self + static mutex _idx_lock; + static thread_key_type& _mt_key; + size_t uw_alloc_size; + + thread_id_type _id; + thread_id_type _rip_id; + mutex _rip_id_lock; +#ifdef _PTHREADS +# ifndef __hpux + // sorry, POSIX threads don't have suspend/resume calls, so it should + // be simulated via cond_wait + __condition<false> _suspend; +# endif +#endif +#ifdef __FIT_WIN32THREADS + unsigned long _thr_id; +#endif + entrance_type _entrance; + void *_param; + size_t _param_sz; + unsigned _flags; + size_t _stack_sz; // stack size, if not 0 +#ifdef __FIT_CREATE_THREAD_STACK_INFO + std::string _stack_on_create; +#endif + friend class Init; + // extern "C", wrap for thread_create +// #ifdef __unix +// friend void *_xcall( void * ); +// #endif +// #ifdef __FIT_WIN32THREADS +// friend unsigned long __stdcall _xcall( void *p ); +// #endif +}; + +template <bool SCOPE> +int __condition<SCOPE>::try_wait_time( const ::timespec *abstime ) +{ +#if defined(__FIT_WIN32THREADS) + MT_LOCK( _lock ); +#endif +#if defined(__FIT_UITHREADS) || defined(_PTHREADS) + scoped_lock _x1( _lock ); +#endif + if ( _val == false ) { +#ifdef __FIT_WIN32THREADS + ResetEvent( _cond ); + time_t ct = time( 0 ); + unsigned ms = abstime->tv_sec >= ct ? (abstime->tv_sec - ct) * 1000 + abstime->tv_nsec / 1000000 : 1; + MT_UNLOCK( _lock ); + int ret = WaitForSingleObject( _cond, ms ); + if ( ret == WAIT_FAILED ) { + return -1; + } + if ( ret == WAIT_TIMEOUT ) { + SetEvent( _cond ); + return ETIME; + } + return 0; +#endif +#if defined(__FIT_UITHREADS) || defined(_PTHREADS) + int ret = 0; + while ( !_val ) { +# ifdef _PTHREADS + ret = pthread_cond_timedwait( &_cond, &_lock._M_lock, abstime ); + if ( ret == ETIMEDOUT ) { + break; + } +# endif +# ifdef __FIT_UITHREADS + ret = cond_timedwait( &_cond, /* &_lock.mutex */ &_lock._M_lock, abstime ); + if ( ret == ETIME ) { + ret = ETIMEDOUT; + } else if ( ret == ETIMEDOUT ) { + break; + } +# endif + } + + return ret; +#endif // _PTHREADS || __FIT_UITHREADS +#ifdef _NOTHREADS + return 0; +#endif + } +#if defined(__FIT_WIN32THREADS) + MT_UNLOCK( _lock ); +#endif + return 0; +} + +template <bool SCOPE> +int __condition<SCOPE>::try_wait_delay( const ::timespec *interval ) +{ +#if defined(__FIT_WIN32THREADS) + MT_LOCK( _lock ); +#endif +#if defined(__FIT_UITHREADS) || defined(_PTHREADS) + scoped_lock _x1( _lock ); +#endif + if ( _val == false ) { +#ifdef WIN32 + _val = false; + ResetEvent( _cond ); + MT_UNLOCK( _lock ); + unsigned ms = interval->tv_sec * 1000 + interval->tv_nsec / 1000000; + int ret = WaitForSingleObject( _cond, ms ); + if ( ret == WAIT_FAILED ) { + return -1; + } + if ( ret == WAIT_TIMEOUT ) { + SetEvent( _cond ); + return ETIME; + } + return 0; +#endif +#if defined(__FIT_UITHREADS) || defined(_PTHREADS) + ::timespec ct; + xmt::gettime( &ct ); + ct += *interval; + + int ret = 0; + while ( !_val ) { +# ifdef _PTHREADS + ret = pthread_cond_timedwait( &_cond, &_lock._M_lock, &ct ); + if ( ret == ETIMEDOUT ) { + break; + } +# endif +# ifdef __FIT_UITHREADS + ret = cond_timedwait( &_cond, /* &_lock.mutex */ &_lock._M_lock, &ct ); + if ( ret == ETIME ) { + ret = ETIMEDOUT; + } else if ( ret == ETIMEDOUT ) { + break; + } +# endif + } + + return ret; +#endif // _PTHREADS || __FIT_UITHREADS + +#ifdef _NOTHREADS + return 0; +#endif + } + +#if defined(__FIT_WIN32THREADS) + MT_UNLOCK( _lock ); +#endif + return 0; +} + +template <bool SCOPE> +int __condition<SCOPE>::wait_time( const ::timespec *abstime ) +{ +#ifdef __FIT_WIN32THREADS + MT_LOCK( _lock ); + _val = false; + ResetEvent( _cond ); + time_t ct = time( 0 ); + unsigned ms = abstime->tv_sec >= ct ? (abstime->tv_sec - ct) * 1000 + abstime->tv_nsec / 1000000 : 1; + MT_UNLOCK( _lock ); + int ret = WaitForSingleObject( _cond, ms ); + if ( ret == WAIT_FAILED ) { + return -1; + } + if ( ret == WAIT_TIMEOUT ) { + SetEvent( _cond ); + return ETIME; + } + return 0; +#endif +#ifdef _PTHREADS + scoped_lock _x1( _lock ); // ?? + _val = false; + int ret = pthread_cond_timedwait( &_cond, &_lock._M_lock, abstime ); + if ( ret == ETIMEDOUT ) { + _val = true; + } + return ret; +#endif // _PTHREADS +#ifdef __FIT_UITHREADS + scoped_lock _x1( _lock ); + _val = false; + int ret; + while ( !_val ) { + ret = cond_timedwait( &_cond, /* &_lock.mutex */ &_lock._M_lock, abstime ); + if ( ret == ETIME ) { + _val = true; + ret = ETIMEDOUT; + } else if ( ret == ETIMEDOUT ) { + _val = true; + } + } + + return ret; +#endif +#ifdef _NOTHREADS + return 0; +#endif +} + +template <bool SCOPE> +int __condition<SCOPE>::wait_delay( const ::timespec *interval ) +{ +#ifdef __FIT_WIN32THREADS + MT_LOCK( _lock ); + _val = false; + ResetEvent( _cond ); + unsigned ms = interval->tv_sec * 1000 + interval->tv_nsec / 1000000; + MT_UNLOCK( _lock ); + int ret = WaitForSingleObject( _cond, ms ); + if ( ret == WAIT_FAILED ) { + return -1; + } + if ( ret == WAIT_TIMEOUT ) { + SetEvent( _cond ); + return ETIME; + } + return 0; +#endif +#if defined(__FIT_UITHREADS) || defined(_PTHREADS) + ::timespec ct; + xmt::gettime( &ct ); + ct += *interval; + + return this->wait_time( &ct ); +#endif +#ifdef _NOTHREADS + return 0; +#endif +} + +pid_t getpid(); +pid_t getppid(); + +} // namespace xmt + +namespace __impl = xmt; // compatibility + +#endif // __XMT_H This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-02-11 17:37:58
|
Revision: 1811 http://complement.svn.sourceforge.net/complement/?rev=1811&view=rev Author: complement Date: 2008-02-11 09:37:55 -0800 (Mon, 11 Feb 2008) Log Message: ----------- base for branch, conversion mt -> wg21 working draft Added Paths: ----------- branches/wg21-thread/include/mt/thread Copied: branches/wg21-thread/include/mt/thread (from rev 1810, branches/wg21-thread/include/mt/xmt.h) =================================================================== --- branches/wg21-thread/include/mt/thread (rev 0) +++ branches/wg21-thread/include/mt/thread 2008-02-11 17:37:55 UTC (rev 1811) @@ -0,0 +1,1760 @@ +// -*- C++ -*- Time-stamp: <07/09/15 10:03:40 ptr> + +/* + * Copyright (c) 1997-1999, 2002-2007 + * Petr Ovtchenkov + * + * Portion Copyright (c) 1999-2001 + * Parallel Graphics Ltd. + * + * Licensed under the Academic Free License version 3.0 + * + */ + +#ifndef __XMT_H +#define __XMT_H + +#ifndef __config_feature_h +#include <config/feature.h> +#endif + +#include <memory> +#include <cstddef> +#include <stdexcept> + +#if !defined(_STLPORT_VERSION) && !defined(__STATIC_CAST) +# define __STATIC_CAST(t,v) static_cast<t>(v) +#endif + +#ifdef WIN32 +# include <windows.h> +# include <memory> +# include <limits> +# define ETIME 62 /* timer expired */ +# pragma warning( disable : 4290) +#endif // WIN32 + +#ifdef __unix +# if defined( _REENTRANT ) && !defined(_NOTHREADS) +# ifdef _PTHREADS +# include <pthread.h> +# include <semaphore.h> +# include <sched.h> +# else +# include <thread.h> +# include <synch.h> +# endif +# elif !defined(_NOTHREADS) // !_REENTRANT +# define _NOTHREADS +# endif +// # define __DLLEXPORT +#endif // __unix + +#include <cerrno> + +#include <mt/time.h> + +#ifdef _REENTRANT + +# define MT_REENTRANT(point,nm) xmt::scoped_lock nm(point) +# define MT_LOCK(point) point.lock() +# define MT_UNLOCK(point) point.unlock() + +#else // !_REENTRANT + +# define MT_REENTRANT(point,nm) ((void)0) +# define MT_REENTRANT_RS(point,nm) ((void)0) +# define MT_LOCK(point) ((void)0) +# define MT_UNLOCK(point) ((void)0) + +#endif // _REENTRANT + +#include <signal.h> + +extern "C" { + +#ifndef SIG_PF // sys/signal.h + +# ifdef WIN32 +typedef void __cdecl SIG_FUNC_TYP(int); +# else +typedef void SIG_FUNC_TYP(int); +# endif +typedef SIG_FUNC_TYP *SIG_TYP; +# define SIG_PF SIG_TYP + +# ifndef SIG_DFL +# define SIG_DFL (SIG_PF)0 +# endif +# ifndef SIG_ERR +# define SIG_ERR (SIG_PF)-1 +# endif +# ifndef SIG_IGN +# define SIG_IGN (SIG_PF)1 +# endif +# ifndef SIG_HOLD +# define SIG_HOLD (SIG_PF)2 +# endif +#endif // SIG_PF + +typedef void siginfo_handler_type( int, siginfo_t *, void * ); + +} // extern "C" + +namespace xmt { + + +// Exceptions + +// class thread_exit; +// class thread_cancel: public thread_exit; +// class thread_error: public exception; + +class lock_error : + public std::exception +{ + private: + int r_; + + public: + + explicit lock_error( int r ) : + r_( r ) + { } + + virtual char const *what() throw() + { return "std::lock_error"; } + + int error() const + { return r_; } +}; + +namespace detail { + +#ifdef __FIT_PSHARED_MUTEX +extern std::string _notpshared; +#endif + +#ifdef __FIT_XSI_THR +extern std::string _notrecursive; +#endif + +} // namespace detail + +// extern __FIT_DECLSPEC void signal_throw( int sig ) throw( int ); +// extern __FIT_DECLSPEC void signal_thread_exit( int sig ); + +// #ifdef __unix +// extern "C" void *_xcall( void * ); // forward declaration +// #endif +// #ifdef WIN32 +// extern "C" unsigned long __stdcall _xcall( void *p ); // forward declaration +// #endif + +#ifndef WIN32 +// using std::size_t; +#endif +#ifdef __GNUC__ + // using std::runtime_error; +#else +using std::runtime_error; +#endif + +#ifndef _WIN32 +class fork_in_parent : + public std::exception +{ + public: + fork_in_parent() throw() + { _pid = 0; } + fork_in_parent( pid_t p ) throw() + { _pid = p; } + virtual ~fork_in_parent() throw() + { } + virtual const char *what() const throw() + { return "class fork_in_parent"; } + pid_t pid() throw() + { return _pid; } + + private: + pid_t _pid; +}; +#endif // !_WIN32 + + +template <bool SCOPE> class __condition; + +// if parameter SCOPE (process scope) true, PTHREAD_PROCESS_SHARED will +// be used; otherwise PTHREAD_PROCESS_PRIVATE. +// Of cause, system must support process scope... +// Linux at 2003-01-19 NOT SUPPORT PTHREAD_PROCESS_SHARED mutex! +// And Windows too! +// +template <bool RECURSIVE_SAFE, bool SCOPE> +class __mutex_base +{ + public: + __mutex_base() + { +#ifdef _PTHREADS + if ( SCOPE || RECURSIVE_SAFE ) { + pthread_mutexattr_t att; + pthread_mutexattr_init( &att ); +# ifdef __FIT_PSHARED_MUTEX + if ( SCOPE ) { + if ( pthread_mutexattr_setpshared( &att, PTHREAD_PROCESS_SHARED ) != 0 ) { + throw std::invalid_argument( detail::_notpshared ); + } + } +# endif // __FIT_PSHARED_MUTEX +# ifdef __FIT_XSI_THR // Unix 98 or X/Open System Interfaces Extention + if ( RECURSIVE_SAFE ) { + if ( pthread_mutexattr_settype( &att, PTHREAD_MUTEX_RECURSIVE ) != 0 ) { + throw std::invalid_argument( detail::_notrecursive ); + } + } +# endif + pthread_mutex_init( &_M_lock, &att ); + pthread_mutexattr_destroy( &att ); + } else { + pthread_mutex_init( &_M_lock, 0 ); + } +#endif // _PTHREADS +#ifdef __FIT_UITHREADS + if ( SCOPE ) { + // or USYNC_PROCESS_ROBUST to detect already initialized mutex + // in process scope + mutex_init( &_M_lock, USYNC_PROCESS, 0 ); + } else { + mutex_init( &_M_lock, 0, 0 ); + } +#endif +#ifdef __FIT_WIN32THREADS + InitializeCriticalSection( &_M_lock ); +#endif + } + + ~__mutex_base() + { +#ifdef _PTHREADS + pthread_mutex_destroy( &_M_lock ); +#endif +#ifdef __FIT_UITHREADS + mutex_destroy( &_M_lock ); +#endif +#ifdef WIN32 + DeleteCriticalSection( &_M_lock ); +#endif + } + + private: + __mutex_base( const __mutex_base& ) + { } + + protected: +#ifdef _PTHREADS + pthread_mutex_t _M_lock; +#endif +#ifdef __FIT_UITHREADS + mutex_t _M_lock; +#endif +#ifdef __FIT_WIN32THREADS + CRITICAL_SECTION _M_lock; +#endif + +#ifndef __FIT_WIN32THREADS + private: + friend class __condition<SCOPE>; +#endif +}; + +#ifdef __FIT_PTHREAD_SPINLOCK + +// The IEEE Std. 1003.1j-2000 introduces functions to implement spinlocks. +template <bool SCOPE> +class __spinlock_base +{ + public: + __spinlock_base() + { +#ifdef _PTHREADS + pthread_spin_init( &_M_lock, SCOPE ? 1 : 0 ); +#endif // _PTHREADS + } + + ~__spinlock_base() + { +#ifdef _PTHREADS + pthread_spin_destroy( &_M_lock ); +#endif + } + protected: +#ifdef _PTHREADS + pthread_spinlock_t _M_lock; +#endif +}; + +#endif // __FIT_PTHREAD_SPINLOCK + +// Portable mutex implementation. If the parameter RECURSIVE_SAFE +// is true, mutex will be recursive safe (detect deadlock). +// If RECURSIVE_SAFE is false, implementation may not to be +// recursive-safe. +// The SCOPE parameter designate mutex scope---shared between +// processes (true), or only inside threads of one process (false). +// Note, that not all OS support interprocess mutex scope +// (for example, Windows and Linux). +template <bool RECURSIVE_SAFE, bool SCOPE> +class __mutex : + public __mutex_base<RECURSIVE_SAFE,SCOPE> +{ + public: + __mutex() + { } + + ~__mutex() + { } + + void lock() + { +#ifdef _PTHREADS + pthread_mutex_lock( &this->_M_lock ); +#endif +#ifdef __FIT_UITHREADS + mutex_lock( &this->_M_lock ); +#endif +#ifdef __FIT_WIN32THREADS + EnterCriticalSection( &this->_M_lock ); +#endif + } + +#if !defined( WIN32 ) || (defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400) + int try_lock() + { +#ifdef _PTHREADS + return pthread_mutex_trylock( &this->_M_lock ); +#endif +#ifdef __FIT_UITHREADS + return mutex_trylock( &this->_M_lock ); +#endif +#ifdef __FIT_WIN32THREADS + return TryEnterCriticalSection( &this->_M_lock ) != 0 ? 0 : -1; +#endif +#ifdef _NOTHREADS + return 0; +#endif + } +#endif // !WIN32 || _WIN32_WINNT >= 0x0400 + + void unlock() + { +#ifdef _PTHREADS + pthread_mutex_unlock( &this->_M_lock ); +#endif +#ifdef __FIT_UITHREADS + mutex_unlock( &this->_M_lock ); +#endif +#ifdef __FIT_WIN32THREADS + LeaveCriticalSection( &this->_M_lock ); +#endif + } + + private: + __mutex( const __mutex& ) + { } + +#ifndef __FIT_WIN32THREADS + private: + friend class __condition<SCOPE>; +#endif +}; + +#ifdef __FIT_PTHREAD_SPINLOCK +// Spinlock-based locks (IEEE Std. 1003.1j-2000) + +template <bool RS, bool SCOPE> class __spinlock; + +template <bool SCOPE> +class __spinlock<false,SCOPE> : + public __spinlock_base<SCOPE> +{ + public: + __spinlock() + { } + + ~__spinlock() + { } + + void lock() + { +# ifdef _PTHREADS + pthread_spin_lock( &this->_M_lock ); +# endif + } + + int try_lock() + { +# ifdef _PTHREADS + return pthread_spin_trylock( &this->_M_lock ); +# endif +# ifdef _NOTHREADS + return 0; +# endif + } + + void unlock() + { +# ifdef _PTHREADS + pthread_spin_unlock( &this->_M_lock ); +# endif + } + + private: + __spinlock( const __spinlock& ) + { } + +}; + +template <bool SCOPE> +class __spinlock<true,SCOPE> : // Recursive safe + public __spinlock_base<SCOPE> +{ + public: + __spinlock() + { } + + ~__spinlock() + { } + + void lock() + { +# ifndef _NOTHREADS +# ifdef _PTHREADS + pthread_t _c_id = pthread_self(); +# endif +# ifdef __FIT_UITHREADS + thread_t _c_id = thr_self(); +# endif + if ( _c_id == _id ) { + ++_count; + return; + } +# ifdef _PTHREADS + pthread_spin_lock( &this->_M_lock ); +# endif + _id = _c_id; + _count = 0; +# endif // !_NOTHREADS + } + + int try_lock() + { +# ifdef _NOTHREADS + return 0; +# else // _NOTHREADS +# ifdef _PTHREADS + pthread_t _c_id = pthread_self(); +# endif +# ifdef __FIT_UITHREADS + thread_t _c_id = thr_self(); +# endif + if ( _c_id == _id ) { + ++_count; + return 0; + } +# ifdef _PTHREADS + int res = pthread_spin_trylock( &this->_M_lock ); +# endif + if ( res != 0 ) { + return res; + } + + _id = _c_id; + _count = 0; + + return 0; +# endif // !_NOTHREADS + } + + void unlock() + { +# ifndef _NOTHREADS + if ( --_count == 0 ) { +# ifdef _PTHREADS + _id = __STATIC_CAST(pthread_t,-1); + pthread_spin_unlock( &this->_M_lock ); +# endif +# endif // !_NOTHREADS + } + } + protected: +# ifndef _NOTHREADS + unsigned _count; +# endif // !_NOTHREADS + +# ifdef _PTHREADS + pthread_t _id; +# endif +# ifdef __FIT_UITHREADS + thread_t _id; +# endif + + private: + __spinlock( const __spinlock& ) + { } +}; +#endif // __FIT_PTHREAD_SPINLOCK + +// Recursive Safe mutex. + +// This specialization need for POSIX and DCE threads, +// because Windows CriticalSection is recursive safe. +// By the way, point for enhancement: __UNIX_98 +// (or XSI---X/Open System Interfaces Extention) has recursive mutex option. +// Another specialization? + +#if (defined(__unix) && !defined(__FIT_XSI_THR)) + +// This specialization need for old POSIX and DCE threads, +// before XSI (X/Open System Interfaces Extention) or Unix 98. +// because Windows CriticalSection is recursive safe, and +// XSI implementation has appropriate mutex parameter (see +// __mutex_base above). + +template <bool SCOPE> +class __mutex<true,SCOPE> : // Recursive Safe + public __mutex_base<true,SCOPE> +{ + public: + __mutex() : + _count( 0 ), +# ifdef __FIT_UITHREADS + _id( __STATIC_CAST(thread_t,-1) ) +# endif +# ifdef _PTHREADS + _id( __STATIC_CAST(pthread_t,-1) ) +# endif + { } + + ~__mutex() + { } + + void lock() + { +# ifndef _NOTHREADS +# ifdef _PTHREADS + pthread_t _c_id = pthread_self(); +# endif +# ifdef __FIT_UITHREADS + thread_t _c_id = thr_self(); +# endif + if ( _c_id == _id ) { + ++_count; + return; + } +# ifdef _PTHREADS + pthread_mutex_lock( &_M_lock ); +# endif +# ifdef __FIT_UITHREADS + mutex_lock( &_M_lock ); +# endif + _id = _c_id; + _count = 0; +# endif // !_NOTHREADS + } + + // Equivalent to lock(), except that if the mutex object referenced + // by mutex is currently locked the call return immediately. + // If mutex is currently owned by the calling thread, the mutex lock count + // incremented by one and the try_lock() function immediately return success + // (value 0). Otherwise, if mutex is currently owned by another thread, + // return error (non-zero). + + int try_lock() + { +# ifdef _NOTHREADS + return 0; +# else // _NOTHREADS +# ifdef _PTHREADS + pthread_t _c_id = pthread_self(); +# endif +# ifdef __FIT_UITHREADS + thread_t _c_id = thr_self(); +# endif + if ( _c_id == _id ) { + ++_count; + return 0; + } +# ifdef _PTHREADS + int res = pthread_mutex_trylock( &_M_lock ); +# endif +# ifdef __FIT_UITHREADS + int res = mutex_trylock( &_M_lock ); +# endif + if ( res != 0 ) { + return res; + } + + _id = _c_id; + _count = 0; + + return 0; +# endif // !_NOTHREADS + } + + void unlock() + { +# ifndef _NOTHREADS + if ( --_count == 0 ) { +# ifdef __FIT_UITHREADS + _id = __STATIC_CAST(thread_t,-1); + mutex_unlock( &_M_lock ); +# endif +# ifdef _PTHREADS + _id = __STATIC_CAST(pthread_t,-1); + pthread_mutex_unlock( &_M_lock ); +# endif +# endif // !_NOTHREADS + } + } + + private: + __mutex( const __mutex& ) + { } + + protected: +# ifndef _NOTHREADS + unsigned _count; +# endif // !_NOTHREADS + +# ifdef _PTHREADS + pthread_t _id; +# endif +# ifdef __FIT_UITHREADS + thread_t _id; +# endif +}; +#endif // __unix && !__FIT_XSI_THR + +#ifdef __FIT_RWLOCK +// Read-write mutex: IEEE Std 1003.1, 2001, 2004 Editions + +template <bool SCOPE> +class __rw_mutex_base +{ + public: + __rw_mutex_base() + { +#ifdef _PTHREADS + if ( SCOPE ) { + pthread_rwlockattr_t att; + pthread_rwlockattr_init( &att ); +# ifdef __FIT_PSHARED_MUTEX + if ( pthread_rwlockattr_setpshared( &att, PTHREAD_PROCESS_SHARED ) != 0 ) { + throw std::invalid_argument( xmt::detail::_notpshared ); + } +# endif // __FIT_PSHARED_MUTEX + pthread_rwlock_init( &_M_lock, &att ); + pthread_rwlockattr_destroy( &att ); + } else { + pthread_rwlock_init( &_M_lock, 0 ); + } +#endif // _PTHREADS +#ifdef __FIT_UITHREADS +#error Fix me! + if ( SCOPE ) { + // or USYNC_PROCESS_ROBUST to detect already initialized mutex + // in process scope + mutex_init( &_M_lock, USYNC_PROCESS, 0 ); + } else { + mutex_init( &_M_lock, 0, 0 ); + } +#endif +#ifdef __FIT_WIN32THREADS +#error Fix me! + InitializeCriticalSection( &_M_lock ); +#endif + } + + ~__rw_mutex_base() + { +#ifdef _PTHREADS + pthread_rwlock_destroy( &_M_lock ); +#endif +#ifdef __FIT_UITHREADS +#error Fix me! + mutex_destroy( &_M_lock ); +#endif +#ifdef WIN32 +#error Fix me! + DeleteCriticalSection( &_M_lock ); +#endif + } + + private: + __rw_mutex_base( const __rw_mutex_base& ) + { } + + protected: +#ifdef _PTHREADS + pthread_rwlock_t _M_lock; +#endif +#ifdef __FIT_UITHREADS +#error Fix me! + mutex_t _M_lock; +#endif +#ifdef __FIT_WIN32THREADS +#error Fix me! + CRITICAL_SECTION _M_lock; +#endif +}; + +template <bool SCOPE> +class __rw_mutex : + public __rw_mutex_base<SCOPE> +{ + public: + __rw_mutex() + { } + + ~__rw_mutex() + { } + + void rdlock() + { +#ifdef _PTHREADS + pthread_rwlock_rdlock( &this->_M_lock ); +#endif +#ifdef __FIT_UITHREADS +#error Fix me! + mutex_lock( &this->_M_lock ); +#endif +#ifdef __FIT_WIN32THREADS +#error Fix me! + EnterCriticalSection( &this->_M_lock ); +#endif + } + + void lock() + { +#ifdef _PTHREADS + pthread_rwlock_wrlock( &this->_M_lock ); +#endif +#ifdef __FIT_UITHREADS +#error Fix me! + mutex_lock( &this->_M_lock ); +#endif +#ifdef __FIT_WIN32THREADS +#error Fix me! + EnterCriticalSection( &this->_M_lock ); +#endif + } + +#if !defined( WIN32 ) || (defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400) + int try_rdlock() + { +#ifdef _PTHREADS + return pthread_rwlock_tryrdlock( &this->_M_lock ); +#endif +#ifdef __FIT_UITHREADS +#error Fix me! + return mutex_trylock( &this->_M_lock ); +#endif +#ifdef __FIT_WIN32THREADS +#error Fix me! + return TryEnterCriticalSection( &this->_M_lock ) != 0 ? 0 : -1; +#endif +#ifdef _NOTHREADS +#error Fix me! + return 0; +#endif + } + + int try_lock() + { +#ifdef _PTHREADS + return pthread_rwlock_trywrlock( &this->_M_lock ); +#endif +#ifdef __FIT_UITHREADS +#error Fix me! + return mutex_trylock( &this->_M_lock ); +#endif +#ifdef __FIT_WIN32THREADS +#error Fix me! + return TryEnterCriticalSection( &this->_M_lock ) != 0 ? 0 : -1; +#endif +#ifdef _NOTHREADS +#error Fix me! + return 0; +#endif + } + +#endif // !WIN32 || _WIN32_WINNT >= 0x0400 + + void unlock() + { +#ifdef _PTHREADS + pthread_rwlock_unlock( &this->_M_lock ); +#endif +#ifdef __FIT_UITHREADS +#error Fix me! + mutex_unlock( &this->_M_lock ); +#endif +#ifdef __FIT_WIN32THREADS +#error Fix me! + LeaveCriticalSection( &this->_M_lock ); +#endif + } + + private: + __rw_mutex( const __rw_mutex& ) + { } +}; + +#endif // __FIT_RWLOCK + +template <class M> +class basic_lock +{ + public: + basic_lock( const M& point, bool initially_locked = true ) : + m( point ), + lk( false ) + { if ( initially_locked ) lock(); } + ~basic_lock() + { if ( lk ) const_cast<M&>(m).unlock(); } + + void lock() + { + if ( lk ) { + throw lock_error( 0 ); + } + const_cast<M&>(m).lock(); + lk = true; + } + + void unlock() + { + if ( !lk ) { + throw lock_error( 0 ); + } + lk = false; + const_cast<M&>(m).unlock(); + } + + private: + basic_lock( const basic_lock& ) + { } + basic_lock& operator =( const basic_lock& ) + { return *this; } + + const M& m; + bool lk; +}; + +#ifdef __FIT_RWLOCK +template <class M> +class basic_read_lock +{ + public: + basic_read_lock( const M& point, bool initially_locked = true ) : + m( point ), + lk( false ) + { if ( initially_locked ) lock(); } + ~basic_read_lock() + { if ( lk ) const_cast<M&>(m).unlock(); } + + void lock() + { + if ( lk ) { + throw lock_error( 0 ); + } + const_cast<M&>(m).rdlock(); + lk = true; + } + + void unlock() + { + if ( !lk ) { + throw lock_error( 0 ); + } + lk = false; + const_cast<M&>(m).unlock(); + } + + private: + basic_read_lock( const basic_read_lock& ) + { } + basic_read_lock& operator =( const basic_read_lock& ) + { return *this; } + + const M& m; + bool lk; +}; +#endif // __FIT_RWLOCK + +typedef __mutex<false,false> mutex; +typedef __mutex<true,false> recursive_mutex; +typedef __mutex<false,true> shared_mutex; +typedef __mutex<true,true> shared_recursive_mutex; +#ifdef __FIT_RWLOCK +typedef __rw_mutex<false> rw_mutex; +#endif // __FIT_RWLOCK +#ifdef __FIT_PTHREAD_SPINLOCK +typedef __spinlock<false,false> spinlock; +typedef __spinlock<true,false> recursive_spinlock; +#endif // __FIT_RWLOCK + +typedef basic_lock<mutex> scoped_lock; +typedef basic_lock<recursive_mutex> recursive_scoped_lock; +#ifdef __FIT_RWLOCK +typedef basic_read_lock<__rw_mutex<false> > rd_scoped_lock; +typedef basic_lock<__rw_mutex<false> > wr_scoped_lock; +#endif // __FIT_RWLOCK +#ifdef __FIT_PTHREAD_SPINLOCK +typedef basic_lock<spinlock> spin_scoped_lock; +typedef basic_lock<recursive_spinlock> recursive_spin_scoped_lock; +#endif // __FIT_RWLOCK + +class native_scoped_lock +{ + public: +#ifdef _PTHREADS + explicit native_scoped_lock( const pthread_mutex_t& m ) : +#endif +#ifdef __FIT_UITHREADS + explicit native_scoped_lock( const mutex_t& m ) : +#endif +#ifdef __FIT_WIN32THREADS + explicit native_scoped_lock( const CRITICAL_SECTION& m ) : +#endif + _M_lock( m ) + { +#ifdef _PTHREADS + pthread_mutex_lock( const_cast<pthread_mutex_t *>(&_M_lock) ); +#endif +#ifdef __FIT_UITHREADS + mutex_lock( const_cast<mutex_t *>(&_M_lock) ); +#endif +#ifdef __FIT_WIN32THREADS + EnterCriticalSection( const_cast<CRITICAL_SECTION *>(&_M_lock) ); +#endif + } + + ~native_scoped_lock() + { +#ifdef _PTHREADS + pthread_mutex_unlock( const_cast<pthread_mutex_t *>(&_M_lock) ); +#endif +#ifdef __FIT_UITHREADS + mutex_unlock( const_cast<mutex_t *>(&_M_lock) ); +#endif +#ifdef __FIT_WIN32THREADS + LeaveCriticalSection( const_cast<CRITICAL_SECTION *>(&_M_lock) ); +#endif + } + + private: + native_scoped_lock( const native_scoped_lock& m ) : + _M_lock( m._M_lock ) + { } +#ifdef _PTHREADS + const pthread_mutex_t& _M_lock; +#endif +#ifdef __FIT_UITHREADS + const mutex_t& _M_lock; +#endif +#ifdef __FIT_WIN32THREADS + const CRITICAL_SECTION& _M_lock; +#endif +}; + +template <bool SCOPE> +class __condition +{ + public: + __condition() : + _val( true ) + { +#ifdef __FIT_WIN32THREADS + _cond = CreateEvent( 0, TRUE, TRUE, 0 ); +#endif +#ifdef _PTHREADS + if ( SCOPE ) { + pthread_condattr_t attr; + pthread_condattr_init( &attr ); + pthread_condattr_setpshared( &attr, PTHREAD_PROCESS_SHARED ); + pthread_cond_init( &_cond, &attr ); + pthread_condattr_destroy( &attr ); + } else { + pthread_cond_init( &_cond, 0 ); + } +#endif +#ifdef __FIT_UITHREADS + cond_init( &_cond, 0, 0 ); +#endif + } + + ~__condition() + { +#ifdef __FIT_WIN32THREADS + CloseHandle( _cond ); +#endif +#ifdef _PTHREADS + pthread_cond_destroy( &_cond ); +#endif +#ifdef __FIT_UITHREADS + cond_destroy( &_cond ); +#endif + } + + bool set( bool __v, bool _broadcast = false ) + { + basic_lock<__mutex<false,SCOPE> > _x1( _lock ); + + bool tmp = _val; + _val = __v; +#ifdef __FIT_WIN32THREADS + if ( __v == true && tmp == false ) { + SetEvent( _cond ); + } else if ( __v == false && tmp == true ) { + ResetEvent( _cond ); + } +#endif +#ifdef __FIT_UITHREADS + if ( __v == true && tmp == false ) { + if ( _broadcast ) { + cond_broadcast( &_cond ); + } else { + cond_signal( &_cond ); + } + } +#endif +#ifdef _PTHREADS + if ( __v == true && tmp == false ) { + if ( _broadcast ) { + pthread_cond_broadcast( &_cond ); + } else { + pthread_cond_signal( &_cond ); + } + } +#endif + return tmp; + } + + bool set() const + { return _val; } + + int try_wait() + { + basic_lock<__mutex<false,SCOPE> > _x1( _lock ); + + if ( _val == false ) { +#ifdef __FIT_WIN32THREADS + _x1.unlock(); + if ( WaitForSingleObject( _cond, -1 ) == WAIT_FAILED ) { + return -1; + } + return 0; +#endif +#if defined(__FIT_UITHREADS) || defined(_PTHREADS) + int ret = 0; + while ( !_val ) { + ret = +#ifdef _PTHREADS + pthread_cond_wait( &_cond, &_lock._M_lock ); +#endif +#ifdef __FIT_UITHREADS + cond_wait( &_cond, &_lock._M_lock ); +#endif + } + return ret; +#endif + } + + return 0; + } + + int wait() + { + basic_lock<__mutex<false,SCOPE> > lk( _lock ); + _val = false; + +#ifdef __FIT_WIN32THREADS + ResetEvent( _cond ); + lk.unlock(); + if ( WaitForSingleObject( _cond, -1 ) == WAIT_FAILED ) { + return -1; + } + return 0; +#endif +#if defined(_PTHREADS) || defined(__FIT_UITHREADS) + int ret; + while ( !_val ) { + ret = +#ifdef _PTHREADS + pthread_cond_wait( &_cond, &_lock._M_lock ); +#endif +#ifdef __FIT_UITHREADS + cond_wait( &_cond, &_lock._M_lock ); +#endif + } + + return ret; +#endif +#ifdef _NOTHREADS + return 0; +#endif + } + + int wait_time( const ::timespec *abstime ); + int wait_time( const ::timespec& abstime ) + { return wait_time( &abstime ); } + + int wait_delay( const ::timespec *abstime ); + int wait_delay( const ::timespec& abstime ) + { return wait_time( &abstime ); } + + int try_wait_time( const ::timespec *abstime ); + int try_wait_time( const ::timespec& abstime ) + { return try_wait_time( &abstime ); } + + int try_wait_delay( const ::timespec *abstime ); + int try_wait_delay( const ::timespec& abstime ) + { return try_wait_delay( &abstime ); } + + int signal( bool _broadcast = false ) + { + basic_lock<__mutex<false,SCOPE> > _x1( _lock ); + + _val = true; +#ifdef __FIT_WIN32THREADS + return SetEvent( _cond ) == FALSE ? -1 : 0; +#endif +#ifdef _PTHREADS + return _broadcast ? pthread_cond_broadcast( &_cond ) : pthread_cond_signal( &_cond ); +#endif +#ifdef __FIT_UITHREADS + return _broadcast ? cond_broadcast( &_cond ) : cond_signal( &_cond ); +#endif +#ifdef _NOTHREADS + return 0; +#endif + } + + protected: +#ifdef __FIT_WIN32THREADS + HANDLE _cond; +#endif +#ifdef _PTHREADS + pthread_cond_t _cond; +#endif +#ifdef __FIT_UITHREADS + cond_t _cond; +#endif + __mutex<false,SCOPE> _lock; + bool _val; + + private: + __condition( const __condition& ) + { } +}; + +typedef __condition<false> condition; + +template <bool SCOPE> +class __semaphore +{ + public: + __semaphore( int cnt = 1 ) + { +#ifdef __FIT_WIN32THREADS + _sem = CreateSemaphore( NULL, cnt, INT_MAX, 0 ); // check! + _cnt = cnt; +#endif +#ifdef __FIT_UITHREADS + sema_init( &_sem, cnt, SCOPE ? USYNC_PROCESS : USYNC_THREAD, 0 ); +#endif +#ifdef _PTHREADS + sem_init( &_sem, SCOPE ? 1 : 0, cnt ); +#endif + } + + ~__semaphore() + { +#ifdef __FIT_WIN32THREADS + CloseHandle( _sem ); +#endif +#ifdef __FIT_UITHREADS + sema_destroy( &_sem ); +#endif +#ifdef _PTHREADS + sem_destroy( &_sem ); +#endif + } + + int wait() + { +#ifdef __FIT_WIN32THREADS + --_cnt; + if ( WaitForSingleObject( _sem, -1 ) == WAIT_FAILED ) { + ++_cnt; + return -1; + } + return 0; +#endif +#ifdef __FIT_UITHREADS + return sema_wait( &_sem ); +#endif +#ifdef _PTHREADS + return sem_wait( &_sem ); +#endif + } + + __FIT_DECLSPEC int wait_time( const ::timespec *t ); // wait for time t, or signal + int wait_time( const ::timespec& t ) + { return wait_time( &t ); } + __FIT_DECLSPEC int wait_delay( const ::timespec *t ); // wait, timeout is delay t, or signal + int wait_delay( const ::timespec& t ) + { return wait_delay( &t ); } + + int try_wait() + { +#ifdef __FIT_WIN32THREADS + return _cnt > 0 ? (--_cnt, this->wait()) : -1; +#endif +#ifdef __FIT_UITHREADS + return sema_trywait( &_sem ); +#endif +#ifdef _PTHREADS + return sem_trywait( &_sem ); +#endif + } + + int post() + { +#ifdef __FIT_WIN32THREADS + return ReleaseSemaphore( _sem, 1, &_cnt ) != 0 ? (++_cnt, 0) : -1; +#endif +#ifdef __FIT_UITHREADS + return sema_post( &_sem ); +#endif +#ifdef _PTHREADS + return sem_post( &_sem ); +#endif + } + + int value() + { +#ifdef __FIT_WIN32THREADS + return static_cast<int>(_cnt); +#endif +#ifdef __FIT_UITHREADS +# warning "No semaphore value for Solaris threads!" +#endif +#ifdef _PTHREADS + int v; + int e = sem_getvalue( &_sem, &v ); + + return e == 0 ? v : -1; +#endif + } + + protected: +#ifdef __FIT_WIN32THREADS + HANDLE _sem; + long _cnt; +#endif +#ifdef __FIT_UITHREADS + sema_t _sem; +#endif +#ifdef _PTHREADS + sem_t _sem; +#endif + private: + __semaphore( const __semaphore& ) + { } +}; + +typedef __semaphore<false> semaphore; + +template <bool SCOPE> +int __semaphore<SCOPE>::wait_time( const ::timespec *abstime ) // wait for time t, or signal +{ +#ifdef __FIT_WIN32THREADS + time_t ct = time( 0 ); + time_t _conv = abstime->tv_sec * 1000 + abstime->tv_nsec / 1000000; + + unsigned ms = _conv >= ct ? _conv - ct : 1; + + if ( WaitForSingleObject( _sem, ms ) == WAIT_OBJECT_0 ) { + return 0; + } + return -1; +#endif +#ifdef __FIT_UITHREADS +#warning "Fix me!" +#endif +#ifdef _PTHREADS +# if !(defined(__FreeBSD__) || defined(__OpenBSD__)) + return sem_timedwait( &_sem, abstime ); +# else + return -1; // not implemented +# endif +#endif +} + +template <bool SCOPE> +int __semaphore<SCOPE>::wait_delay( const ::timespec *interval ) // wait, timeout is delay t, or signal +{ +#ifdef __FIT_WIN32THREADS + unsigned ms = interval->tv_sec * 1000 + interval->tv_nsec / 1000000; + + if ( WaitForSingleObject( _sem, ms ) == WAIT_OBJECT_0 ) { + return 0; + } + return -1; +#endif +#ifdef __FIT_UITHREADS +#warning "Fix me!" +#endif +#ifdef _PTHREADS + timespec st; + xmt::gettime( &st ); + st += *interval; +# if !(defined(__FreeBSD__) || defined(__OpenBSD__)) + return sem_timedwait( &_sem, &st ); +# else + return -1; // not implemented +# endif +#endif +} + +template <bool SCOPE> +class __barrier +{ + public: + __barrier( unsigned cnt = 2 ) + { +#ifdef _PTHREADS + pthread_barrierattr_t attr; + pthread_barrierattr_init( &attr ); + pthread_barrierattr_setpshared( &attr, SCOPE ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE ); + pthread_barrier_init( &_barr, &attr, cnt ); + pthread_barrierattr_destroy( &attr ); +#endif + } + + ~__barrier() + { +#ifdef _PTHREADS + pthread_barrier_destroy( &_barr ); +#endif + } + + int wait() + { +#ifdef _PTHREADS + return pthread_barrier_wait( &_barr ); +#endif + } + + private: +#ifdef _PTHREADS + pthread_barrier_t _barr; +#endif +}; + +typedef __barrier<false> barrier; + +__FIT_DECLSPEC void fork() throw( fork_in_parent, std::runtime_error ); +__FIT_DECLSPEC void become_daemon() throw( fork_in_parent, std::runtime_error ); +__FIT_DECLSPEC void block_signal( int sig ); +__FIT_DECLSPEC void unblock_signal( int sig ); +__FIT_DECLSPEC int signal_handler( int sig, SIG_PF ); +__FIT_DECLSPEC int signal_handler( int sig, siginfo_handler_type ); + +class Thread +{ + public: +#ifdef _PTHREADS + typedef void * ret_t; +#endif +#ifdef __FIT_WIN32THREADS + typedef long ret_t; +#endif + + typedef ret_t (*entrance_type)( void * ); +#ifdef __FIT_WIN32THREADS + typedef unsigned long thread_key_type; + typedef HANDLE thread_id_type; + // typedef unsigned long thread_id_type; +#endif +#ifdef _PTHREADS + typedef pthread_key_t thread_key_type; + typedef pthread_t thread_id_type; +#endif +#ifdef __FIT_UITHREADS + typedef thread_key_t thread_key_type; + typedef thread_t thread_id_type; +#endif + + enum { + // thread mode flags +#ifdef __FIT_UITHREADS // __STL_SOLARIS_THREADS + bound = THR_BOUND, + detached = THR_DETACHED, + new_lwp = THR_NEW_LWP, + suspended = THR_SUSPENDED, + daemon = THR_DAEMON, +#endif +#if defined(_PTHREADS) + bound = PTHREAD_SCOPE_SYSTEM, // otherwise, PTHREAD_SCOPE_PROCESS, default + detached = PTHREAD_CREATE_DETACHED,// otherwise, PTHREAD_CREATE_JOINABLE, default + new_lwp = 0, // pthread_setconcurrency( pthread_getconcurrency() + 1 ); + suspended = 0, + daemon = detached, +#endif +#ifdef __FIT_WIN32THREADS + bound = 0, + detached = 0x2, + new_lwp = 0, + suspended = CREATE_SUSPENDED, + daemon = detached, +#endif + // state flags + goodbit = 0x00, + badbit = 0x01 + }; + + class Init + { + public: + Init(); + ~Init(); + private: + static int& _count; + }; + + __FIT_DECLSPEC Thread( unsigned flags = 0 ); + + explicit __FIT_DECLSPEC Thread( entrance_type entrance, const void *p = 0, size_t psz = 0, unsigned flags = 0, size_t stack_sz = 0 ); + + __FIT_DECLSPEC ~Thread(); + + __FIT_DECLSPEC + void launch( entrance_type entrance, const void *p = 0, size_t psz = 0, size_t stack_sz = 0 ); + + __FIT_DECLSPEC ret_t join(); + __FIT_DECLSPEC int suspend(); + __FIT_DECLSPEC int resume(); + __FIT_DECLSPEC int kill( int sig ); +#ifdef __FIT_UITHREADS + static __FIT_DECLSPEC int join_all(); +#endif + static __FIT_DECLSPEC void signal_exit( int sig ); // signal handler +#if defined(_PTHREADS) + static int yield() + { return sched_yield(); } +#endif + + bool good() const + { /* Locker lk( _llock ); */ return (_id != bad_thread_id); } + bool bad() const + { /* Locker lk( _llock ); */ return (_id == bad_thread_id); } + bool is_join_req() const // if true, you can (and should) use join() + { scoped_lock lk( _rip_id_lock ); return (_rip_id != bad_thread_id) && ((_flags & (daemon | detached)) == 0); } + + __FIT_DECLSPEC bool is_self(); + + static __FIT_DECLSPEC int xalloc(); + long& iword( int __idx ) + { + // _STLP_ASSERT( is_self() ); + return *static_cast<long *>(_alloc_uw( __idx )); + } + void*& pword( int __idx ) + { + // _STLP_ASSERT( is_self() ); + return *reinterpret_cast<void **>(_alloc_uw( __idx )); + } + + static thread_key_type mtkey() + { return _mt_key; } + + static const thread_id_type bad_thread_id; + + protected: + static __FIT_DECLSPEC void _exit( int code = 0 ); + + private: + Thread( const Thread& ) + { } + + bool _not_run() const + { /* Locker lk( _llock ); */ return _id == bad_thread_id; } + void _create( const void *p, size_t psz ) throw( std::runtime_error); + + static void *_call( void *p ); +#ifdef WIN32 + statuc unsigned long __stdcall _call( void *p ); +#endif + + static void unexpected(); + static void terminate(); + + // assume that sizeof( long ) >= sizeof( void * ); + // otherwise, #ifdef workaround should be here. + // At present, I don't know such OS. +#if 1 + typedef long _uw_alloc_type; +#endif + typedef std::allocator<_uw_alloc_type> alloc_type; + __FIT_DECLSPEC void _dealloc_uw(); + __FIT_DECLSPEC _uw_alloc_type *_alloc_uw( int __idx ); + + static alloc_type alloc; + static int _idx; // user words index + static int _self_idx; // user words index, that word point to self + static mutex _idx_lock; + static thread_key_type& _mt_key; + size_t uw_alloc_size; + + thread_id_type _id; + thread_id_type _rip_id; + mutex _rip_id_lock; +#ifdef _PTHREADS +# ifndef __hpux + // sorry, POSIX threads don't have suspend/resume calls, so it should + // be simulated via cond_wait + __condition<false> _suspend; +# endif +#endif +#ifdef __FIT_WIN32THREADS + unsigned long _thr_id; +#endif + entrance_type _entrance; + void *_param; + size_t _param_sz; + unsigned _flags; + size_t _stack_sz; // stack size, if not 0 +#ifdef __FIT_CREATE_THREAD_STACK_INFO + std::string _stack_on_create; +#endif + friend class Init; + // extern "C", wrap for thread_create +// #ifdef __unix +// friend void *_xcall( void * ); +// #endif +// #ifdef __FIT_WIN32THREADS +// friend unsigned long __stdcall _xcall( void *p ); +// #endif +}; + +template <bool SCOPE> +int __condition<SCOPE>::try_wait_time( const ::timespec *abstime ) +{ +#if defined(__FIT_WIN32THREADS) + MT_LOCK( _lock ); +#endif +#if defined(__FIT_UITHREADS) || defined(_PTHREADS) + scoped_lock _x1( _lock ); +#endif + if ( _val == false ) { +#ifdef __FIT_WIN32THREADS + ResetEvent( _cond ); + time_t ct = time( 0 ); + unsigned ms = abstime->tv_sec >= ct ? (abstime->tv_sec - ct) * 1000 + abstime->tv_nsec / 1000000 : 1; + MT_UNLOCK( _lock ); + int ret = WaitForSingleObject( _cond, ms ); + if ( ret == WAIT_FAILED ) { + return -1; + } + if ( ret == WAIT_TIMEOUT ) { + SetEvent( _cond ); + return ETIME; + } + return 0; +#endif +#if defined(__FIT_UITHREADS) || defined(_PTHREADS) + int ret = 0; + while ( !_val ) { +# ifdef _PTHREADS + ret = pthread_cond_timedwait( &_cond, &_lock._M_lock, abstime ); + if ( ret == ETIMEDOUT ) { + break; + } +# endif +# ifdef __FIT_UITHREADS + ret = cond_timedwait( &_cond, /* &_lock.mutex */ &_lock._M_lock, abstime ); + if ( ret == ETIME ) { + ret = ETIMEDOUT; + } else if ( ret == ETIMEDOUT ) { + break; + } +# endif + } + + return ret; +#endif // _PTHREADS || __FIT_UITHREADS +#ifdef _NOTHREADS + return 0; +#endif + } +#if defined(__FIT_WIN32THREADS) + MT_UNLOCK( _lock ); +#endif + return 0; +} + +template <bool SCOPE> +int __condition<SCOPE>::try_wait_delay( const ::timespec *interval ) +{ +#if defined(__FIT_WIN32THREADS) + MT_LOCK( _lock ); +#endif +#if defined(__FIT_UITHREADS) || defined(_PTHREADS) + scoped_lock _x1( _lock ); +#endif + if ( _val == false ) { +#ifdef WIN32 + _val = false; + ResetEvent( _cond ); + MT_UNLOCK( _lock ); + unsigned ms = interval->tv_sec * 1000 + interval->tv_nsec / 1000000; + int ret = WaitForSingleObject( _cond, ms ); + if ( ret == WAIT_FAILED ) { + return -1; + } + if ( ret == WAIT_TIMEOUT ) { + SetEvent( _cond ); + return ETIME; + } + return 0; +#endif +#if defined(__FIT_UITHREADS) || defined(_PTHREADS) + ::timespec ct; + xmt::gettime( &ct ); + ct += *interval; + + int ret = 0; + while ( !_val ) { +# ifdef _PTHREADS + ret = pthread_cond_timedwait( &_cond, &_lock._M_lock, &ct ); + if ( ret == ETIMEDOUT ) { + break; + } +# endif +# ifdef __FIT_UITHREADS + ret = cond_timedwait( &_cond, /* &_lock.mutex */ &_lock._M_lock, &ct ); + if ( ret == ETIME ) { + ret = ETIMEDOUT; + } else if ( ret == ETIMEDOUT ) { + break; + } +# endif + } + + return ret; +#endif // _PTHREADS || __FIT_UITHREADS + +#ifdef _NOTHREADS + return 0; +#endif + } + +#if defined(__FIT_WIN32THREADS) + MT_UNLOCK( _lock ); +#endif + return 0; +} + +template <bool SCOPE> +int __condition<SCOPE>::wait_time( const ::timespec *abstime ) +{ +#ifdef __FIT_WIN32THREADS + MT_LOCK( _lock ); + _val = false; + ResetEvent( _cond ); + time_t ct = time( 0 ); + unsigned ms = abstime->tv_sec >= ct ? (abstime->tv_sec - ct) * 1000 + abstime->tv_nsec / 1000000 : 1; + MT_UNLOCK( _lock ); + int ret = WaitForSingleObject( _cond, ms ); + if ( ret == WAIT_FAILED ) { + return -1; + } + if ( ret == WAIT_TIMEOUT ) { + SetEvent( _cond ); + return ETIME; + } + return 0; +#endif +#ifdef _PTHREADS + scoped_lock _x1( _lock ); // ?? + _val = false; + int ret = pthread_cond_timedwait( &_cond, &_lock._M_lock, abstime ); + if ( ret == ETIMEDOUT ) { + _val = true; + } + return ret; +#endif // _PTHREADS +#ifdef __FIT_UITHREADS + scoped_lock _x1( _lock ); + _val = false; + int ret; + while ( !_val ) { + ret = cond_timedwait( &_cond, /* &_lock.mutex */ &_lock._M_lock, abstime ); + if ( ret == ETIME ) { + _val = true; + ret = ETIMEDOUT; + } else if ( ret == ETIMEDOUT ) { + _val = true; + } + } + + return ret; +#endif +#ifdef _NOTHREADS + return 0; +#endif +} + +template <bool SCOPE> +int __condition<SCOPE>::wait_delay( const ::timespec *interval ) +{ +#ifdef __FIT_WIN32THREADS + MT_LOCK( _lock ); + _val = false; + ResetEvent( _cond ); + unsigned ms = interval->tv_sec * 1000 + interval->tv_nsec / 1000000; + MT_UNLOCK( _lock ); + int ret = WaitForSingleObject( _cond, ms ); + if ( ret == WAIT_FAILED ) { + return -1; + } + if ( ret == WAIT_TIMEOUT ) { + SetEvent( _cond ); + return ETIME; + } + return 0; +#endif +#if defined(__FIT_UITHREADS) || defined(_PTHREADS) + ::timespec ct; + xmt::gettime( &ct ); + ct += *interval; + + return this->wait_time( &ct ); +#endif +#ifdef _NOTHREADS + return 0; +#endif +} + +pid_t getpid(); +pid_t getppid(); + +} // namespace xmt + +namespace __impl = xmt; // compatibility + +#endif // __XMT_H This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-02-11 17:27:36
|
Revision: 1810 http://complement.svn.sourceforge.net/complement/?rev=1810&view=rev Author: complement Date: 2008-02-11 09:27:31 -0800 (Mon, 11 Feb 2008) Log Message: ----------- base for branch, conversion mt -> wg21 working draft Added Paths: ----------- branches/wg21-thread/lib/mt/ Copied: branches/wg21-thread/lib/mt (from rev 1809, trunk/complement/explore/lib/mt) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-02-11 17:27:03
|
Revision: 1809 http://complement.svn.sourceforge.net/complement/?rev=1809&view=rev Author: complement Date: 2008-02-11 09:27:00 -0800 (Mon, 11 Feb 2008) Log Message: ----------- base for branch, conversion mt -> wg21 working draft Added Paths: ----------- branches/wg21-thread/include/mt/ Copied: branches/wg21-thread/include/mt (from rev 1808, trunk/complement/explore/include/mt) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-02-11 17:25:54
|
Revision: 1808 http://complement.svn.sourceforge.net/complement/?rev=1808&view=rev Author: complement Date: 2008-02-11 09:25:38 -0800 (Mon, 11 Feb 2008) Log Message: ----------- base for branch, conversion mt -> wg21 working draft Added Paths: ----------- branches/wg21-thread/lib/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-02-11 17:25:33
|
Revision: 1807 http://complement.svn.sourceforge.net/complement/?rev=1807&view=rev Author: complement Date: 2008-02-11 09:25:27 -0800 (Mon, 11 Feb 2008) Log Message: ----------- base for branch, conversion mt -> wg21 working draft Added Paths: ----------- branches/wg21-thread/include/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-02-11 17:23:38
|
Revision: 1806 http://complement.svn.sourceforge.net/complement/?rev=1806&view=rev Author: complement Date: 2008-02-11 09:23:34 -0800 (Mon, 11 Feb 2008) Log Message: ----------- base for branch, conversion mt -> wg21 working draft Added Paths: ----------- branches/wg21-thread/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-02-11 16:17:03
|
Revision: 1805 http://complement.svn.sourceforge.net/complement/?rev=1805&view=rev Author: complement Date: 2008-02-11 08:16:59 -0800 (Mon, 11 Feb 2008) Log Message: ----------- moved to exam's perf suite and went to STlport, SVN https://stlport.svn.sourceforge.net/svnroot/stlport/trunk/perf Removed Paths: ------------- trunk/complement/explore/perf/STL/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <com...@us...> - 2008-01-17 06:59:33
|
Revision: 1804 http://complement.svn.sourceforge.net/complement/?rev=1804&view=rev Author: complement Date: 2008-01-16 22:59:31 -0800 (Wed, 16 Jan 2008) Log Message: ----------- rules to generate mps from mp, that was made from gnuplot. Modified Paths: -------------- trunk/complement/explore/Makefiles/ChangeLog trunk/complement/explore/Makefiles/gmake/topdoc.mak Modified: trunk/complement/explore/Makefiles/ChangeLog =================================================================== --- trunk/complement/explore/Makefiles/ChangeLog 2008-01-16 22:12:50 UTC (rev 1803) +++ trunk/complement/explore/Makefiles/ChangeLog 2008-01-17 06:59:31 UTC (rev 1804) @@ -1,3 +1,8 @@ +2008-01-17 Petr Ovtchenkov <pt...@is...> + + * gmake/topdoc.mak: rules to generate mps from mp, that was made + from gnuplot. + 2008-01-11 Petr Ovtchenkov <pt...@is...> * gmake/gcc.mak, gmake/CC.mak, gmake/aCC.mak: fix _FORCE_CXX macro Modified: trunk/complement/explore/Makefiles/gmake/topdoc.mak =================================================================== --- trunk/complement/explore/Makefiles/gmake/topdoc.mak 2008-01-16 22:12:50 UTC (rev 1803) +++ trunk/complement/explore/Makefiles/gmake/topdoc.mak 2008-01-17 06:59:31 UTC (rev 1804) @@ -1,4 +1,4 @@ -# Time-stamp: <08/01/08 15:22:06 ptr> +# Time-stamp: <08/01/17 09:39:54 ptr> # # Copyright (c) 2007,2008 # Petr Ovtchenkov @@ -63,7 +63,7 @@ $(foreach fig,$(PDFNAMES),$(eval $(call dep_mp,$(fig)))) define pdf_ -$(1).pdf: $($(1)_SRC_TEX) $($(1)_MPS) $($(1)_EXTRA) +$(1).pdf: $($(1)_SRC_TEX) $($(1)_MPS) $($(1)_MP_MPS) $($(1)_EXTRA) pdflatex $$< endef @@ -82,28 +82,28 @@ endef define dep_mps -#TMP1 := $$(basename $$(notdir $(1))).mps -#$(2) := $($(2)) $${TMP1} -#ALLMP := $$(ALLMP) $(1) +$(1)_MP_MPS := $(patsubst %.mp,%.mps,$(notdir ${$(1)_SRC_MP})) +ALLMP += ${$(1)_SRC_MP} endef -#define rule_mps -#TMP2 := $$(OUTPUT_DIR)/$$(basename $$(notdir $(1))).0 -#$$(TMP2): $(1) -# $$(chdirs) -# sed -i -e 's/beginfig(.)/beginfig(0)/' $$< -# (cd $${OUTPUT_DIR}; mpost --tex=latex ../`basename $$<`) -# rm -f $(1).mpx -# -#TMP1 := $$(basename $$(notdir $(1))).mps -#$$(TMP1): $$(TMP2) -# ln -sf $$< $$@ -#endef +$(foreach mp,$(PDFNAMES),$(eval $(call dep_mps,$(mp)))) +define rule_mps +TMP2 := $$(OUTPUT_DIR)/$$(basename $$(notdir $(1))).0 +$$(TMP2): $(1) + sed -i -e 's/beginfig(.)/beginfig(0)/' $$< + (cd $${OUTPUT_DIR}; mpost --tex=latex ../`basename $$<`) + rm -f $(1)x + +TMP1 := $$(basename $$(notdir $(1))).mps +$$(TMP1): $$(TMP2) + ln -sf $$< $$@ +endef + $(foreach pdf,$(PDFNAMES),$(eval $(call pdf_,$(pdf)))) ALLFIG := $(sort $(ALLFIG)) -# ALLMP := $(sort $(ALLMP)) +ALLMP := $(sort $(ALLMP)) $(foreach fig,$(ALLFIG),$(eval $(call rule_mp,$(fig)))) -# $(foreach mp,$(ALLMP),$(eval $(call rule_mps,$(mp)))) +$(foreach mp,$(ALLMP),$(eval $(call rule_mps,$(mp)))) .PHONY: ${PHONY} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |