1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
19
#include "apr_reslist.h"
20
#include "apr_thread_proc.h"
24
#endif /* APR_HAVE_TIME_H */
30
fprintf(stderr, "this program requires APR thread support\n");
37
#define RESLIST_SMAX 10
38
#define RESLIST_HMAX 20
39
#define RESLIST_TTL APR_TIME_C(350000) /* 35 ms */
40
#define CONSUMER_THREADS 25
41
#define CONSUMER_ITERATIONS 250
42
#define CONSTRUCT_SLEEP_TIME APR_TIME_C(250000) /* 25 ms */
43
#define DESTRUCT_SLEEP_TIME APR_TIME_C(100000) /* 10 ms */
44
#define WORK_DELAY_SLEEP_TIME APR_TIME_C(150000) /* 15 ms */
47
apr_interval_time_t sleep_upon_construct;
48
apr_interval_time_t sleep_upon_destruct;
57
static apr_status_t my_constructor(void **resource, void *params,
61
my_parameters_t *my_params = params;
63
/* Create some resource */
64
res = apr_palloc(pool, sizeof(*res));
65
res->id = my_params->c_count++;
67
printf("++ constructing new resource [id:%d, #%d/%d]\n", res->id,
68
my_params->c_count, my_params->d_count);
70
/* Sleep for awhile, to simulate construction overhead. */
71
apr_sleep(my_params->sleep_upon_construct);
73
/* Set the resource so it can be managed by the reslist */
78
static apr_status_t my_destructor(void *resource, void *params,
81
my_resource_t *res = resource;
82
my_parameters_t *my_params = params;
84
printf("-- destructing old resource [id:%d, #%d/%d]\n", res->id,
85
my_params->c_count, ++my_params->d_count);
87
apr_sleep(my_params->sleep_upon_destruct);
94
apr_reslist_t *reslist;
95
apr_interval_time_t work_delay_sleep;
98
static void * APR_THREAD_FUNC resource_consuming_thread(apr_thread_t *thd,
102
my_thread_info_t *thread_info = data;
103
apr_reslist_t *rl = thread_info->reslist;
106
for (i = 0; i < CONSUMER_ITERATIONS; i++) {
109
rv = apr_reslist_acquire(rl, &vp);
110
if (rv != APR_SUCCESS) {
111
fprintf(stderr, "Failed to retrieve resource from reslist\n");
112
apr_thread_exit(thd, rv);
116
printf(" [tid:%d,iter:%d] using resource id:%d\n", thread_info->tid,
118
apr_sleep(thread_info->work_delay_sleep);
119
/* simulate a 5% chance of the resource being bad */
120
if ( drand48() < 0.95 ) {
121
rv = apr_reslist_release(rl, res);
122
if (rv != APR_SUCCESS) {
123
fprintf(stderr, "Failed to return resource to reslist\n");
124
apr_thread_exit(thd, rv);
128
printf("invalidating resource id:%d\n", res->id) ;
129
rv = apr_reslist_invalidate(rl, res);
130
if (rv != APR_SUCCESS) {
131
fprintf(stderr, "Failed to invalidate resource\n");
132
apr_thread_exit(thd, rv);
141
static void test_timeout(apr_reslist_t *rl)
144
my_resource_t *resources[RESLIST_HMAX];
149
printf("Setting timeout to 1000us: ");
150
apr_reslist_timeout_set(rl, 1000);
151
fprintf(stdout, "OK\n");
153
/* deplete all possible resources from the resource list
154
* so that the next call will block until timeout is reached
155
* (since there are no other threads to make a resource
159
for (i = 0; i < RESLIST_HMAX; i++) {
160
rv = apr_reslist_acquire(rl, (void**)&resources[i]);
161
if (rv != APR_SUCCESS) {
162
fprintf(stderr, "couldn't acquire resource: %d\n", rv);
167
/* next call will block until timeout is reached */
168
rv = apr_reslist_acquire(rl, &vp);
169
if (!APR_STATUS_IS_TIMEUP(rv)) {
170
fprintf(stderr, "apr_reslist_acquire()->%d instead of TIMEUP\n",
176
/* release the resources; otherwise the destroy operation
179
for (i = 0; i < RESLIST_HMAX; i++) {
180
rv = apr_reslist_release(rl, &resources[i]);
181
if (rv != APR_SUCCESS) {
182
fprintf(stderr, "couldn't release resource: %d\n", rv);
188
static apr_status_t test_reslist(apr_pool_t *parpool)
193
my_parameters_t *params;
195
apr_thread_t *my_threads[CONSUMER_THREADS];
196
my_thread_info_t my_thread_info[CONSUMER_THREADS];
199
printf("Creating child pool.......................");
200
rv = apr_pool_create(&pool, parpool);
201
if (rv != APR_SUCCESS) {
202
fprintf(stderr, "Error creating child pool\n");
207
/* Create some parameters that will be passed into each
208
* constructor and destructor call. */
209
params = apr_pcalloc(pool, sizeof(*params));
210
params->sleep_upon_construct = CONSTRUCT_SLEEP_TIME;
211
params->sleep_upon_destruct = DESTRUCT_SLEEP_TIME;
213
/* We're going to want 10 blocks of data from our target rmm. */
214
printf("Creating resource list:\n"
215
" min/smax/hmax: %d/%d/%d\n"
216
" ttl: %" APR_TIME_T_FMT "\n", RESLIST_MIN, RESLIST_SMAX,
217
RESLIST_HMAX, RESLIST_TTL);
218
rv = apr_reslist_create(&rl, RESLIST_MIN, RESLIST_SMAX, RESLIST_HMAX,
219
RESLIST_TTL, my_constructor, my_destructor,
221
if (rv != APR_SUCCESS) {
222
fprintf(stderr, "Error allocating shared memory block\n");
225
fprintf(stdout, "OK\n");
227
printf("Creating %d threads", CONSUMER_THREADS);
228
for (i = 0; i < CONSUMER_THREADS; i++) {
230
my_thread_info[i].tid = i;
231
my_thread_info[i].reslist = rl;
232
my_thread_info[i].work_delay_sleep = WORK_DELAY_SLEEP_TIME;
233
rv = apr_thread_create(&my_threads[i], NULL,
234
resource_consuming_thread, &my_thread_info[i],
236
if (rv != APR_SUCCESS) {
237
fprintf(stderr, "Failed to create thread %d\n", i);
243
printf("Waiting for threads to finish");
244
for (i = 0; i < CONSUMER_THREADS; i++) {
245
apr_status_t thread_rv;
247
apr_thread_join(&thread_rv, my_threads[i]);
248
if (rv != APR_SUCCESS) {
249
fprintf(stderr, "Failed to join thread %d\n", i);
257
printf("Destroying resource list.................");
258
rv = apr_reslist_destroy(rl);
259
if (rv != APR_SUCCESS) {
265
apr_pool_destroy(pool);
279
printf("APR Resource List Test\n");
280
printf("======================\n\n");
282
printf("Initializing the pool............................");
283
if (apr_pool_create(&pool, NULL) != APR_SUCCESS) {
284
printf("could not initialize pool\n");
289
rv = test_reslist(pool);
290
if (rv != APR_SUCCESS) {
291
printf("Resource list test FAILED: [%d] %s\n",
292
rv, apr_strerror(rv, errmsg, sizeof(errmsg)));
295
printf("Resource list test passed!\n");
300
#endif /* APR_HAS_THREADS */