Further testing of locks.
[idzebra-moved-to-github.git] / util / tstflock.c
1 /*
2  * Copyright (C) 1995-2006, Index Data ApS
3  * See the file LICENSE for details.
4  *
5  * $Id: tstflock.c,v 1.10 2006-06-30 13:02:20 adam Exp $
6  */
7
8 #include <assert.h>
9 #include <stdlib.h>
10 #include <yaz/test.h>
11 #include <yaz/log.h>
12 #if YAZ_POSIX_THREADS
13 #include <pthread.h>
14 #endif
15 #ifdef WIN32
16 #include <windows.h>
17 #include <process.h>
18 #endif
19
20 #include <idzebra/flock.h>
21 #if HAVE_UNISTD_H
22 #include <unistd.h>
23 #endif
24 #include <string.h>
25
26 static char seq[1000];
27 static char *seqp = 0;
28
29 #define NUM_THREADS 100
30
31 static void small_sleep()
32 {
33 #ifdef WIN32
34     Sleep(50);
35 #else
36     sleep(1);
37 #endif
38 }
39
40 void *run_func(void *arg)
41 {
42     int i;
43     int *pdata = (int*) arg;
44     int use_write_lock = *pdata;
45     ZebraLockHandle lh = zebra_lock_create(0, "my.LCK");
46     for (i = 0; i<2; i++)
47     {
48         int write_lock;
49
50         if (use_write_lock == 2)
51             write_lock = (rand() & 3) == 3 ? 1 : 0;
52         else
53             write_lock = use_write_lock;
54             
55         if (write_lock)
56         {
57             zebra_lock_w(lh);
58             
59             *seqp++ = 'L';
60             small_sleep();
61             *seqp++ = 'U';
62             
63             zebra_unlock(lh);
64         }
65         else
66         {
67             zebra_lock_r(lh);
68             
69             *seqp++ = 'l';
70             small_sleep();
71             *seqp++ = 'u';
72             
73             zebra_unlock(lh);
74         }
75     }
76     zebra_lock_destroy(lh);
77     *pdata = 123;
78     return 0;
79 }
80
81 #ifdef WIN32
82 DWORD WINAPI ThreadProc(void *p)
83 {
84     run_func(p);
85     return 0;
86 }
87 #endif
88
89 static void tst_thread(int num, int write_flag)
90 {
91 #ifdef WIN32
92     HANDLE handles[NUM_THREADS];
93     DWORD dwThreadId[NUM_THREADS];
94 #endif
95 #if YAZ_POSIX_THREADS
96     pthread_t child_thread[NUM_THREADS];
97 #endif
98     int i, id[NUM_THREADS];
99
100     seqp = seq;
101     assert (num <= NUM_THREADS);
102     for (i = 0; i < num; i++)
103     {
104         id[i] = write_flag;
105 #if YAZ_POSIX_THREADS
106         pthread_create(&child_thread[i], 0 /* attr */, run_func, &id[i]);
107 #endif
108 #ifdef WIN32
109         if (1)
110         {
111             void *pData = &id[i];
112             handles[i] = CreateThread(
113                 NULL,              /* default security attributes */
114                 0,                 /* use default stack size */
115                 ThreadProc,        /* thread function */
116                 pData,             /* argument to thread function */
117                 0,                 /* use default creation flags */
118                 &dwThreadId[i]);   /* returns the thread identifier */
119         }
120
121 #endif
122     }
123 #if YAZ_POSIX_THREADS
124     for (i = 0; i<num; i++)
125         pthread_join(child_thread[i], 0);
126 #endif
127 #ifdef WIN32
128     WaitForMultipleObjects(num, handles, TRUE, INFINITE);
129 #endif
130     for (i = 0; i < num; i++)
131         YAZ_CHECK(id[i] == 123);
132     *seqp++ = '\0';
133 }
134
135 static void tst()
136 {
137     tst_thread(4, 1); /* write locks */
138 #if 0
139     printf("seq=%s\n", seq);
140 #endif
141     if (1)
142     {
143         int i = 0;
144         while (seq[i])
145         {
146             YAZ_CHECK_EQ(seq[i], 'L');
147             YAZ_CHECK_EQ(seq[i+1], 'U');
148             i = i + 2;
149         }
150     }
151
152 #if 0
153     tst_thread(6, 0);  /* read locks */
154     printf("seq=%s\n", seq);
155 #endif
156 #if 0
157     tst_thread(20, 2); /* random locks */
158     printf("seq=%s\n", seq);
159 #endif
160 }
161
162 int main(int argc, char **argv)
163 {
164     YAZ_CHECK_INIT(argc, argv);
165
166     yaz_log_time_format("%s:%!");
167
168     zebra_flock_init();
169
170     tst();
171
172     YAZ_CHECK_TERM;
173 }
174
175
176 /*
177  * Local variables:
178  * c-basic-offset: 4
179  * indent-tabs-mode: nil
180  * End:
181  * vim: shiftwidth=4 tabstop=8 expandtab
182  */
183