From: Dennis Schafroth Date: Thu, 20 May 2010 14:25:31 +0000 (+0200) Subject: Merge branch 'master' of ssh://git.indexdata.com/home/git/pub/yaz X-Git-Tag: v4.0.9~3 X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=commitdiff_plain;h=21d73f362bc5a84885739838fb6695d6c60c1187;hp=cd093c26605b9c436123e15c3a5989624e38831c Merge branch 'master' of ssh://git.indexdata.com/home/git/pub/yaz --- diff --git a/configure.ac b/configure.ac index 59a283c..d158abd 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ dnl This file is part of the YAZ toolkit. dnl Copyright (C) 1995-2010 Index Data AC_PREREQ([2.60]) -AC_INIT([yaz],[4.0.8],[yaz-help@indexdata.dk]) +AC_INIT([yaz],[4.0.9],[yaz-help@indexdata.dk]) AC_CONFIG_SRCDIR([configure.ac]) AC_CONFIG_AUX_DIR([config]) AM_INIT_AUTOMAKE([1.9]) diff --git a/debian/changelog b/debian/changelog index 9f0a2f6..75da0ed 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +yaz (4.0.9-1indexdata) unstable; urgency=low + + * New yaz_thread functions + + -- Adam Dickmeiss Wed, 19 May 2010 15:19:25 +0200 + yaz (4.0.8-2indexdata) unstable; urgency=low * Remove *.la files diff --git a/debian/control b/debian/control index 4e5a91d..911d10e 100644 --- a/debian/control +++ b/debian/control @@ -37,7 +37,7 @@ Description: documentation for the Z39.50 toolkit This package includes HTML documentation for YAZ. Package: libyaz4-dev -Depends: libyaz4 (= ${Source-Version}), libxslt1-dev, libicu36-dev|libicu-dev, libgnutls-dev, tcl8.3|tclsh +Depends: libyaz4 (= ${Source-Version}), libxslt1-dev, libicu36-dev|libicu-dev, tcl8.3|tclsh Replaces: yaz-devel Conflicts: yaz-devel, libyaz-dev, libyaz2-dev, libyaz3-dev Section: libdevel diff --git a/doc/common b/doc/common index cc80f24..ca4e4fa 160000 --- a/doc/common +++ b/doc/common @@ -1 +1 @@ -Subproject commit cc80f24dcf550d033c2fdf29ea35b4e0961f357d +Subproject commit ca4e4fa028634b4e07f011eb6375e205ae96c709 diff --git a/doc/installation.xml b/doc/installation.xml index e052ec0..7ef2b4e 100644 --- a/doc/installation.xml +++ b/doc/installation.xml @@ -527,8 +527,8 @@ HAVE_TCL, TCL If HAVE_TCL is set to 1, nmake will - use the ASN.1 compiler (Tcl based). You must set - TCL to the full path of the Tcl + use the ASN.1 compiler (Tcl based). + You must set TCL to the full path of the Tcl interpreter. diff --git a/include/yaz/Makefile.am b/include/yaz/Makefile.am index 72e5896..015c5a7 100644 --- a/include/yaz/Makefile.am +++ b/include/yaz/Makefile.am @@ -20,7 +20,8 @@ pkginclude_HEADERS= backend.h ccl.h ccl_xml.h cql.h rpn2cql.h comstack.h \ z-univ.h z-oclcui.h zes-expi.h zes-exps.h zes-order.h zes-pquery.h \ zes-psched.h zes-admin.h zes-pset.h zes-update.h zes-update0.h \ zoom.h z-charneg.h charneg.h soap.h srw.h zgdu.h matchstr.h json.h \ - file_glob.h dirent.h thread_id.h gettimeofday.h shptr.h + file_glob.h dirent.h thread_id.h gettimeofday.h shptr.h thread_create.h \ + spipe.h EXTRA_DIST = yaz-version.h.in diff --git a/include/yaz/dirent.h b/include/yaz/dirent.h index 1f5d68f..b565ec2 100644 --- a/include/yaz/dirent.h +++ b/include/yaz/dirent.h @@ -43,9 +43,9 @@ struct dirent { typedef struct DIR DIR; -DIR *opendir (const char *path); -struct dirent *readdir (DIR *dd); -void closedir (DIR *dd); +YAZ_EXPORT DIR *opendir (const char *path); +YAZ_EXPORT struct dirent *readdir (DIR *dd); +YAZ_EXPORT void closedir (DIR *dd); YAZ_END_CDECL diff --git a/include/yaz/match_glob.h b/include/yaz/match_glob.h index 6ff7eaf..a06e02e 100644 --- a/include/yaz/match_glob.h +++ b/include/yaz/match_glob.h @@ -46,6 +46,7 @@ YAZ_BEGIN_CDECL * (any number of any char) * (zero or more) */ +YAZ_EXPORT int yaz_match_glob(const char *glob, const char *text); YAZ_END_CDECL diff --git a/include/yaz/spipe.h b/include/yaz/spipe.h new file mode 100644 index 0000000..1b48650 --- /dev/null +++ b/include/yaz/spipe.h @@ -0,0 +1,78 @@ +/* This file is part of the YAZ toolkit. + * Copyright (C) 1995-2010 Index Data. + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Index Data nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file spipe.h + * \brief socket-pipe header + */ +#ifndef YAZ_SPIPE_H +#define YAZ_SPIPE_H + +#include +#include +#include +#include + +YAZ_BEGIN_CDECL + +/** \brief YAZ socket pipe opaque pointer */ +typedef struct yaz_spipe *yaz_spipe_t; + +/** \brief create socket pipe + \param port_to_use port that we temporarily bind to + \param err_msg error message reference (0 if not to be set) + \returns 0 on failure; != 0 on success + */ +YAZ_EXPORT yaz_spipe_t yaz_spipe_create(int port_to_use, WRBUF *err_msg); + +/** \brief destroys socket pipe + \param p socket pipe pointer + */ +YAZ_EXPORT void yaz_spipe_destroy(yaz_spipe_t p); + +/** \brief returns reading socket + \param p socket pipe pointer + */ +YAZ_EXPORT int yaz_spipe_get_read_fd(yaz_spipe_t p); + +/** \brief returns writing socket + \param p socket pipe pointer + */ +YAZ_EXPORT int yaz_spipe_get_write_fd(yaz_spipe_t p); + +YAZ_END_CDECL + +#endif +/* + * Local variables: + * c-basic-offset: 4 + * c-file-style: "Stroustrup" + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ + diff --git a/include/yaz/thread_create.h b/include/yaz/thread_create.h new file mode 100644 index 0000000..d93bc03 --- /dev/null +++ b/include/yaz/thread_create.h @@ -0,0 +1,73 @@ +/* This file is part of the YAZ toolkit. + * Copyright (C) 1995-2010 Index Data. + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Index Data nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file thread_create.h + * \brief Implements thread creation wrappers + */ +#ifndef YAZ_THREAD_CREATE_H +#define YAZ_THREAD_CREATE_H + +#include +#include +#include + +YAZ_BEGIN_CDECL + +/** \brief Thread Identifier opaque pointer */ +typedef struct yaz_thread *yaz_thread_t; + +/** \brief create thread + \param start_routine thread handler + \param arg user data to be passed to handler + \returns thread_id identifier if successful; NULL on failure + */ +YAZ_EXPORT yaz_thread_t yaz_thread_create(void *(*start_routine)(void *p), void *arg); + +/** \brief join thread + \param tp thread_id reference .. Will be 0 upon completion + \param value_ptr ref pointer to routine result (0 if not needed) +*/ +YAZ_EXPORT void yaz_thread_join(yaz_thread_t *tp, void **value_ptr); + +/** \brief detach thread + \param tp thread_id reference .. Will be 0 upon completion +*/ +void yaz_thread_detach(yaz_thread_t *tp); + +YAZ_END_CDECL + +#endif +/* + * Local variables: + * c-basic-offset: 4 + * c-file-style: "Stroustrup" + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ + diff --git a/src/Makefile.am b/src/Makefile.am index 46e2e50..d8dd1e9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -103,7 +103,7 @@ libyaz_la_SOURCES=version.c options.c log.c \ iconv_encode_marc8.c iconv_encode_iso_8859_1.c iconv_encode_wchar.c \ iconv_decode_marc8.c iconv_decode_iso5426.c iconv_decode_danmarc.c sc.c \ json.c xml_include.c file_glob.c dirent.c mutex-p.h mutex.c condvar.c \ - thread_id.c gettimeofday.c + thread_id.c gettimeofday.c thread_create.c spipe.c libyaz_la_LDFLAGS=-version-info $(YAZ_VERSION_INFO) diff --git a/src/condvar.c b/src/condvar.c index 5bbd92a..19291d4 100644 --- a/src/condvar.c +++ b/src/condvar.c @@ -48,11 +48,14 @@ struct yaz_cond { void yaz_cond_create(YAZ_COND *p) { - *p = (YAZ_COND) malloc(sizeof(**p)); #ifdef WIN32 + *p = (YAZ_COND) malloc(sizeof(**p)); InitializeConditionVariable(&(*p)->cond); #elif YAZ_POSIX_THREADS + *p = (YAZ_COND) malloc(sizeof(**p)); pthread_cond_init(&(*p)->cond, 0); +#else + *p = 0; #endif } @@ -72,6 +75,7 @@ void yaz_cond_destroy(YAZ_COND *p) int yaz_cond_wait(YAZ_COND p, YAZ_MUTEX m, const struct timeval *abstime) { #ifdef WIN32 + BOOL v; if (abstime) { struct timeval tval_now; @@ -81,10 +85,11 @@ int yaz_cond_wait(YAZ_COND p, YAZ_MUTEX m, const struct timeval *abstime) sec = abstime->tv_sec - tval_now.tv_sec; msec = (abstime->tv_usec - tval_now.tv_usec) / 1000; - return SleepConditionVariableCS(&p->cond, &m->handle, sec*1000 + msec); + v = SleepConditionVariableCS(&p->cond, &m->handle, sec*1000 + msec); } else - return SleepConditionVariableCS(&p->cond, &m->handle, INFINITE); + v = SleepConditionVariableCS(&p->cond, &m->handle, INFINITE); + return v ? 0 : -1; #elif YAZ_POSIX_THREADS if (abstime) { diff --git a/src/spipe.c b/src/spipe.c new file mode 100644 index 0000000..52c922a --- /dev/null +++ b/src/spipe.c @@ -0,0 +1,283 @@ +/* This file is part of the YAZ toolkit. + * Copyright (C) 1995-2010 Index Data + * See the file LICENSE for details. + */ + +/** + * \file spipe.c + * \brief Implements socket-pipes + * + */ +#if HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#if HAVE_UNISTD_H +#include +#endif + +#ifdef WIN32 +#include +#define YAZ_INVALID_SOCKET INVALID_SOCKET +#else +#define YAZ_INVALID_SOCKET -1 +#include +#endif + +#if HAVE_NETINET_IN_H +#include +#endif +#if HAVE_NETDB_H +#include +#endif +#if HAVE_ARPA_INET_H +#include +#endif +#if HAVE_NETINET_TCP_H +#include +#endif +#if HAVE_SYS_SOCKET_H +#include +#endif + +#if HAVE_NETINET_IN_H +#include +#endif +#if HAVE_NETDB_H +#include +#endif +#if HAVE_ARPA_INET_H +#include +#endif +#if HAVE_NETINET_TCP_H +#include +#endif + +struct yaz_spipe { + int m_fd[2]; + int m_socket; +}; + +static void yaz_spipe_close(int *fd) +{ +#ifdef WIN32 + if (*fd != YAZ_INVALID_SOCKET) + closesocket(*fd); +#else + if (*fd != YAZ_INVALID_SOCKET) + close(*fd); +#endif + *fd = YAZ_INVALID_SOCKET; +} + +static int nonblock(int s) +{ +#ifdef WIN32 + unsigned long tru = 1; + if (ioctlsocket(s, FIONBIO, &tru)) + return -1; +#else + if (fcntl(s, F_SETFL, O_NONBLOCK)) + return -1; +#endif + return 0; +} + +yaz_spipe_t yaz_spipe_create(int port_to_use, WRBUF *err_msg) +{ + yaz_spipe_t p = xmalloc(sizeof(*p)); + +#ifdef WIN32 + { + WSADATA wsaData; + WORD wVersionRequested = MAKEWORD(2, 0); + if (WSAStartup( wVersionRequested, &wsaData)) + { + if (err_msg) + wrbuf_printf(*err_msg, "WSAStartup failed"); + xfree(p); + return 0; + } + } +#endif + p->m_fd[0] = p->m_fd[1] = YAZ_INVALID_SOCKET; + p->m_socket = YAZ_INVALID_SOCKET; + + if (port_to_use) + { + struct sockaddr_in add; + struct sockaddr *addr = 0; + unsigned int tmpadd; + struct sockaddr caddr; +#ifdef WIN32 + int caddr_len = sizeof(caddr); +#else + socklen_t caddr_len = sizeof(caddr); +#endif + fd_set write_set; + + // create server socket + p->m_socket = socket(AF_INET, SOCK_STREAM, 0); + if (p->m_socket == YAZ_INVALID_SOCKET) + { + if (err_msg) + wrbuf_printf(*err_msg, "socket call failed"); + yaz_spipe_destroy(p); + return 0; + } +#ifndef WIN32 + { + unsigned long one = 1; + if (setsockopt(p->m_socket, SOL_SOCKET, SO_REUSEADDR, (char*) + &one, sizeof(one))) + { + if (err_msg) + wrbuf_printf(*err_msg, "setsockopt call failed"); + yaz_spipe_destroy(p); + return 0; + } + } +#endif + // bind server socket + add.sin_family = AF_INET; + add.sin_port = htons(port_to_use); + add.sin_addr.s_addr = INADDR_ANY; + addr = ( struct sockaddr *) &add; + + if (bind(p->m_socket, addr, sizeof(struct sockaddr_in))) + { + if (err_msg) + wrbuf_printf(*err_msg, "could not bind to socket"); + yaz_spipe_destroy(p); + return 0; + } + + if (listen(p->m_socket, 3) < 0) + { + if (err_msg) + wrbuf_printf(*err_msg, "could not listen on socket"); + yaz_spipe_destroy(p); + return 0; + } + + // client socket + tmpadd = (unsigned) inet_addr("127.0.0.1"); + if (!tmpadd) + { + if (err_msg) + wrbuf_printf(*err_msg, "inet_addr failed"); + yaz_spipe_destroy(p); + return 0; + } + + memcpy(&add.sin_addr.s_addr, &tmpadd, sizeof(struct in_addr)); + p->m_fd[1] = socket(AF_INET, SOCK_STREAM, 0); + if (p->m_fd[1] == YAZ_INVALID_SOCKET) + { + if (err_msg) + wrbuf_printf(*err_msg, "socket call failed (2)"); + yaz_spipe_destroy(p); + return 0; + } + nonblock(p->m_fd[1]); + + if (connect(p->m_fd[1], addr, sizeof(*addr))) + { + if ( +#ifdef WIN32 + WSAGetLastError() != WSAEWOULDBLOCK +#else + errno != EINPROGRESS +#endif + ) + { + if (err_msg) + wrbuf_printf(*err_msg, "connect call failed"); + yaz_spipe_destroy(p); + return 0; + } + } + + /* server accept */ + p->m_fd[0] = accept(p->m_socket, &caddr, &caddr_len); + if (p->m_fd[0] == YAZ_INVALID_SOCKET) + { + if (err_msg) + wrbuf_printf(*err_msg, "accept failed"); + yaz_spipe_destroy(p); + return 0; + } + + /* complete connect */ + FD_ZERO(&write_set); + FD_SET(p->m_fd[1], &write_set); + if (select(p->m_fd[1]+1, 0, &write_set, 0, 0) != 1) + { + if (err_msg) + wrbuf_printf(*err_msg, "could not complete connect"); + yaz_spipe_destroy(p); + return 0; + } + yaz_spipe_close(&p->m_socket); + } + else + { +#ifdef WIN32 + yaz_spipe_destroy(p); + return 0; +#else + if (pipe(p->m_fd)) + { + if (err_msg) + wrbuf_printf(*err_msg, "pipe call failed"); + yaz_spipe_destroy(p); + return 0; + } + assert(p->m_fd[0] != YAZ_INVALID_SOCKET); + assert(p->m_fd[1] != YAZ_INVALID_SOCKET); +#endif + } + + return p; +} + +void yaz_spipe_destroy(yaz_spipe_t p) +{ + yaz_spipe_close(&p->m_fd[0]); + yaz_spipe_close(&p->m_fd[1]); + yaz_spipe_close(&p->m_socket); + xfree(p); +#ifdef WIN32 + WSACleanup(); +#endif +} + +int yaz_spipe_get_read_fd(yaz_spipe_t p) +{ + return p->m_fd[0]; +} + +int yaz_spipe_get_write_fd(yaz_spipe_t p) +{ + return p->m_fd[1]; +} + + +/* + * Local variables: + * c-basic-offset: 4 + * c-file-style: "Stroustrup" + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ + diff --git a/src/thread_create.c b/src/thread_create.c new file mode 100644 index 0000000..16be9c5 --- /dev/null +++ b/src/thread_create.c @@ -0,0 +1,129 @@ +/* This file is part of the YAZ toolkit. + * Copyright (C) 1995-2010 Index Data + * See the file LICENSE for details. + */ + +/** + * \file thread_create.c + * \brief Implements thread creation wrappers + * + */ +#if HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#if YAZ_POSIX_THREADS +#include +#endif +#ifdef WIN32 +#include +#include +#endif + +struct yaz_thread { +#if YAZ_POSIX_THREADS + pthread_t id; +#else +#ifdef WIN32 + HANDLE handle; + void *(*routine)(void *p); +#endif + void *data; +#endif +}; + +#ifdef WIN32 +unsigned int __stdcall win32_routine(void *p) +{ + yaz_thread_t t = (yaz_thread_t) p; + void *userdata = t->data; + t->data = t->routine(userdata); + _endthreadex(0); + return 0; +} +#endif + +yaz_thread_t yaz_thread_create(void *(*start_routine)(void *p), void *arg) +{ + yaz_thread_t t = xmalloc(sizeof(*t)); +#if YAZ_POSIX_THREADS + int r = pthread_create(&t->id, 0, start_routine, arg); + if (r) + { + xfree(t); + t = 0; + } +#else +#ifdef WIN32 + /* we create a wrapper on windows and pass yaz_thread struct to that */ + unsigned threadID; + uintptr_t ex_ret; + t->data = arg; /* use data for both input and output */ + t->routine = start_routine; + ex_ret = _beginthreadex(NULL, 0, win32_routine, t, 0, &threadID); + if (ex_ret == -1L) + { + xfree(t); + t = 0; + } + t->handle = (HANDLE) ex_ret; +#else + t->data = start_routine(arg); +#endif +#endif + return t; +} + +void yaz_thread_join(yaz_thread_t *tp, void **value_ptr) +{ + if (*tp) + { +#ifdef YAZ_POSIX_THREADS + pthread_join((*tp)->id, value_ptr); +#else +#ifdef WIN32 + WaitForSingleObject((*tp)->handle, INFINITE); + CloseHandle((*tp)->handle); +#endif + if (value_ptr) + *value_ptr = (*tp)->data; +#endif + xfree(*tp); + *tp = 0; + } +} + +void yaz_thread_detach(yaz_thread_t *tp) +{ + if (*tp) + { +#ifdef YAZ_POSIX_THREADS + pthread_detach((*tp)->id); +#else +#ifdef WIN32 + CloseHandle((*tp)->handle); +#endif +#endif + xfree(*tp); + *tp = 0; + } +} + +/* + * Local variables: + * c-basic-offset: 4 + * c-file-style: "Stroustrup" + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ + diff --git a/test/test_mutex.c b/test/test_mutex.c index 52853b1..a4483fc 100644 --- a/test/test_mutex.c +++ b/test/test_mutex.c @@ -7,6 +7,7 @@ #include #include +#include #if HAVE_SYS_TIME_H #include #endif @@ -53,30 +54,61 @@ static void tst_cond(void) return; yaz_cond_create(&c); - YAZ_CHECK(c); - if (!c) - return; - - r = yaz_gettimeofday(&abstime); - YAZ_CHECK_EQ(r, 0); - - abstime.tv_sec += 1; /* wait 1 second */ - - r = yaz_cond_wait(c, p, &abstime); - YAZ_CHECK(r != 0); + if (c) + { + r = yaz_gettimeofday(&abstime); + YAZ_CHECK_EQ(r, 0); + + abstime.tv_sec += 1; /* wait 1 second */ + + r = yaz_cond_wait(c, p, &abstime); + YAZ_CHECK(r != 0); + } yaz_cond_destroy(&c); YAZ_CHECK(c == 0); yaz_mutex_destroy(&p); YAZ_CHECK(p == 0); } +static void *my_handler(void *arg) +{ + int *mydata = (int*) arg; + (*mydata)++; + return mydata; +} + +static void tst_create_thread(void) +{ + void *return_data; + int mydata = 42; + yaz_thread_t t[2]; + + t[0] = yaz_thread_create(my_handler, &mydata); + YAZ_CHECK(t[0]); + t[1] = yaz_thread_create(my_handler, &mydata); + YAZ_CHECK(t[1]); + + return_data = 0; + yaz_thread_join(&t[0], &return_data); + YAZ_CHECK(!t[0]); + YAZ_CHECK(return_data == &mydata); + + return_data = 0; + yaz_thread_join(&t[1], &return_data); + YAZ_CHECK(!t[1]); + YAZ_CHECK(return_data == &mydata); + + YAZ_CHECK_EQ(mydata, 44); +} + int main (int argc, char **argv) { YAZ_CHECK_INIT(argc, argv); YAZ_CHECK_LOG(); tst_mutex(); tst_cond(); + tst_create_thread(); YAZ_CHECK_TERM; } diff --git a/win/makefile b/win/makefile index 7ba0dcb..7933622 100644 --- a/win/makefile +++ b/win/makefile @@ -286,7 +286,7 @@ MT=echo LINK_LIBS= kernel32.lib ws2_32.lib advapi32.lib \ $(ICONV_LIB) $(LIBXML2_LIB) $(LIBXSLT_LIB) -COMMON_LNK_OPTIONS= /nologo /subsystem:windows /machine:i386 /incremental:no +COMMON_LNK_OPTIONS= /nologo /subsystem:windows /incremental:no DEBUG_LNK_OPTIONS= /debug @@ -504,6 +504,8 @@ MISC_OBJS= \ $(OBJDIR)\iconv_decode_iso5426.obj \ $(OBJDIR)\iconv_decode_danmarc.obj \ $(OBJDIR)\mutex.obj \ + $(OBJDIR)\thread_create.obj \ + $(OBJDIR)\spipe.obj \ $(OBJDIR)\gettimeofday.obj \ $(OBJDIR)\json.obj \ $(OBJDIR)\sc.obj \ diff --git a/yaz.spec.in b/yaz.spec.in index 40a7783..0749222 100644 --- a/yaz.spec.in +++ b/yaz.spec.in @@ -36,7 +36,7 @@ Retrieval. %package -n libyaz4-devel Summary: Z39.50 Library - development package Group: Development/Libraries -Requires: libyaz4 = %{version} libxml2-devel libxslt-devel libicu-devel gnutls-devel %{TCPWRAPPER} +Requires: libyaz4 = %{version} libxml2-devel libxslt-devel libicu-devel Conflicts: libyaz-devel %description -n libyaz4-devel @@ -73,6 +73,7 @@ make CFLAGS="$RPM_OPT_FLAGS" rm -fr ${RPM_BUILD_ROOT} make prefix=${RPM_BUILD_ROOT}/%{_prefix} mandir=${RPM_BUILD_ROOT}/%{_mandir} \ libdir=${RPM_BUILD_ROOT}/%{_libdir} install +rm ${RPM_BUILD_ROOT}/%{_libdir}/*.la %clean rm -fr ${RPM_BUILD_ROOT}