Index: src/OFTCPSocket.m ================================================================== --- src/OFTCPSocket.m +++ src/OFTCPSocket.m @@ -15,11 +15,13 @@ #include #include #ifndef HAVE_GETADDRINFO #include +#ifndef _WIN32 #include +#endif #endif #import "OFTCPSocket.h" #import "OFExceptions.h" @@ -28,19 +30,19 @@ #endif #ifndef HAVE_GETADDRINFO #import "OFThread.h" -static OFObject *lock = nil; +static OFMutex *mutex = nil; #endif @implementation OFTCPSocket #ifndef HAVE_GETADDRINFO + (void)initialize { if (self == [OFTCPSocket class]) - lock = [[OFObject alloc] init]; + mutex = [[OFMutex alloc] init]; } #endif - (void)dealloc { @@ -90,52 +92,58 @@ struct servent *se; struct sockaddr_in addr; uint16_t port; char **ip; - @synchronized (lock) { - if ((he = gethostbyname([node cString])) == NULL) - @throw [OFAddressTranslationFailedException - newWithClass: isa - andNode: node - andService: service]; - - if ((se = getservbyname([service cString], "TCP")) != NULL) - port = se->s_port; - else if ((port = htons(atoi([service cString]))) == 0) - @throw [OFAddressTranslationFailedException - newWithClass: isa - andNode: node - andService: service]; - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = port; - - if (he->h_addrtype != AF_INET || - (sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) - @throw [OFConnectionFailedException - newWithClass: isa - andNode: node - andService: service]; - - for (ip = he->h_addr_list; *ip != NULL; ip++) { - memcpy(&addr.sin_addr.s_addr, *ip, he->h_length); - - if (connect(sock, (struct sockaddr*)&addr, - sizeof(addr)) == -1) - continue; - - connected = YES; - - break; - } - - if (!connected) { - close(sock); - sock = INVALID_SOCKET; - } + [mutex lock]; + + if ((he = gethostbyname([node cString])) == NULL) { + [mutex unlock]; + @throw [OFAddressTranslationFailedException + newWithClass: isa + andNode: node + andService: service]; + } + + if ((se = getservbyname([service cString], "TCP")) != NULL) + port = se->s_port; + else if ((port = htons(atoi([service cString]))) == 0) { + [mutex unlock]; + @throw [OFAddressTranslationFailedException + newWithClass: isa + andNode: node + andService: service]; + } + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = port; + + if (he->h_addrtype != AF_INET || + (sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { + [mutex unlock]; + @throw [OFConnectionFailedException + newWithClass: isa + andNode: node + andService: service]; + } + + for (ip = he->h_addr_list; *ip != NULL; ip++) { + memcpy(&addr.sin_addr.s_addr, *ip, he->h_length); + + if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) + continue; + + connected = YES; + break; + } + + [mutex unlock]; + + if (!connected) { + close(sock); + sock = INVALID_SOCKET; } #endif if (sock == INVALID_SOCKET) @throw [OFConnectionFailedException newWithClass: isa @@ -190,43 +198,51 @@ @throw [OFBindFailedException newWithClass: isa andNode: node andService: service andFamily: family]; - @synchronized (lock) { - if ((he = gethostbyname([node cString])) == NULL) - @throw [OFAddressTranslationFailedException - newWithClass: isa - andNode: node - andService: service]; - - if ((se = getservbyname([service cString], "TCP")) != NULL) - port = se->s_port; - else if ((port = htons(atoi([service cString]))) == 0) - @throw [OFAddressTranslationFailedException - newWithClass: isa - andNode: node - andService: service]; - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = port; - - if (he->h_addrtype != AF_INET || he->h_addr_list[0] == NULL) - @throw [OFAddressTranslationFailedException - newWithClass: isa - andNode: node - andService: service]; - - memcpy(&addr.sin_addr.s_addr, he->h_addr_list[0], he->h_length); - - if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) - @throw [OFBindFailedException newWithClass: isa - andNode: node - andService: service - andFamily: family]; - } + [mutex lock]; + + if ((he = gethostbyname([node cString])) == NULL) { + [mutex unlock]; + @throw [OFAddressTranslationFailedException + newWithClass: isa + andNode: node + andService: service]; + } + + if ((se = getservbyname([service cString], "TCP")) != NULL) + port = se->s_port; + else if ((port = htons(atoi([service cString]))) == 0) { + [mutex unlock]; + @throw [OFAddressTranslationFailedException + newWithClass: isa + andNode: node + andService: service]; + } + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = port; + + if (he->h_addrtype != AF_INET || he->h_addr_list[0] == NULL) { + [mutex lock]; + @throw [OFAddressTranslationFailedException + newWithClass: isa + andNode: node + andService: service]; + } + + memcpy(&addr.sin_addr.s_addr, he->h_addr_list[0], he->h_length); + + [mutex unlock]; + + if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) + @throw [OFBindFailedException newWithClass: isa + andNode: node + andService: service + andFamily: family]; #endif return self; } Index: src/OFThread.h ================================================================== --- src/OFThread.h +++ src/OFThread.h @@ -61,11 +61,11 @@ id retval; #endif } /** - * \param obj An object that is passed to the main method as a copy + * \param obj An object that is passed to the main method as a copy or nil * \return A new, autoreleased thread */ + threadWithObject: (id)obj; /** @@ -87,11 +87,11 @@ * \param key The Thread Local Storage key */ + (id)objectForTLSKey: (OFTLSKey*)key; /** - * \param obj An object that is passed to the main method as a copy + * \param obj An object that is passed to the main method as a copy or nil * \return An initialized OFThread. */ - initWithObject: (id)obj; /** @@ -109,5 +109,33 @@ * * \return The object returned by the main method of the thread. */ - join; @end + +/** + * A class for creating mutual exclusions. + */ +@interface OFMutex: OFObject +{ +#ifndef _WIN32 + pthread_mutex_t mutex; +#else + HANDLE mutex; +#endif +} + +/** + * \return A new, autoreleased mutex. + */ ++ mutex; + +/** + * Locks the mutex. + */ +- lock; + +/** + * Unlocks the mutex. + */ +- unlock; +@end Index: src/OFThread.m ================================================================== --- src/OFThread.m +++ src/OFThread.m @@ -168,9 +168,57 @@ #endif c = isa; [super dealloc]; @throw [OFInitializationFailedException newWithClass: c]; } + + return self; +} +@end + +@implementation OFMutex ++ mutex +{ + return [[[self alloc] init] autorelease]; +} + +- init +{ + self = [super init]; + +#ifndef _WIN32 + if (pthread_mutex_init(&mutex, NULL)) { +#else + if ((mutex = CreateMutex(NULL, FALSE, NULL)) == NULL) { +#endif + Class c = isa; + [self dealloc]; + @throw [OFInitializationFailedException newWithClass: c]; + } + + return self; +} + +- lock +{ + /* FIXME: Add error-handling */ +#ifndef _WIN32 + pthread_mutex_lock(&mutex); +#else + WaitForSingleObject(mutex, INFINITE); +#endif + + return self; +} + +- unlock +{ + /* FIXME: Add error-handling */ +#ifndef _WIN32 + pthread_mutex_unlock(&mutex); +#else + ReleaseMutex(mutex); +#endif return self; } @end