1251876Speter/* Licensed to the Apache Software Foundation (ASF) under one or more
2251876Speter * contributor license agreements.  See the NOTICE file distributed with
3251876Speter * this work for additional information regarding copyright ownership.
4251876Speter * The ASF licenses this file to You under the Apache License, Version 2.0
5251876Speter * (the "License"); you may not use this file except in compliance with
6251876Speter * the License.  You may obtain a copy of the License at
7251876Speter *
8251876Speter *     http://www.apache.org/licenses/LICENSE-2.0
9251876Speter *
10251876Speter * Unless required by applicable law or agreed to in writing, software
11251876Speter * distributed under the License is distributed on an "AS IS" BASIS,
12251876Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13251876Speter * See the License for the specific language governing permissions and
14251876Speter * limitations under the License.
15251876Speter */
16251876Speter
17251876Speter#include "apu.h"
18251876Speter#include "apr_queue.h"
19251876Speter#include "apr_thread_pool.h"
20251876Speter#include "apr_time.h"
21251876Speter#include "abts.h"
22251876Speter#include "testutil.h"
23251876Speter
24251876Speter#if APR_HAS_THREADS
25251876Speter
26251876Speter#define NUMBER_CONSUMERS    3
27251876Speter#define CONSUMER_ACTIVITY   4
28251876Speter#define NUMBER_PRODUCERS    4
29251876Speter#define PRODUCER_ACTIVITY   5
30251876Speter#define QUEUE_SIZE          100
31251876Speter
32251876Speterstatic apr_queue_t *queue;
33251876Speter
34251876Speterstatic void * APR_THREAD_FUNC consumer(apr_thread_t *thd, void *data)
35251876Speter{
36251876Speter    long sleeprate;
37251876Speter    abts_case *tc = data;
38251876Speter    apr_status_t rv;
39251876Speter    void *v;
40251876Speter
41251876Speter    sleeprate = 1000000/CONSUMER_ACTIVITY;
42251876Speter    apr_sleep((rand() % 4) * 1000000); /* sleep random seconds */
43251876Speter
44251876Speter    while (1)
45251876Speter    {
46251876Speter        rv = apr_queue_pop(queue, &v);
47251876Speter
48251876Speter        if (rv == APR_EINTR)
49251876Speter            continue;
50251876Speter
51251876Speter        if (rv == APR_EOF)
52251876Speter            break;
53251876Speter
54251876Speter        ABTS_TRUE(tc, v == NULL);
55251876Speter        ABTS_TRUE(tc, rv == APR_SUCCESS);
56251876Speter
57251876Speter        apr_sleep(sleeprate); /* sleep this long to acheive our rate */
58251876Speter    }
59251876Speter
60251876Speter    return NULL;
61251876Speter}
62251876Speter
63251876Speterstatic void * APR_THREAD_FUNC producer(apr_thread_t *thd, void *data)
64251876Speter{
65251876Speter    long sleeprate;
66251876Speter    abts_case *tc = data;
67251876Speter    apr_status_t rv;
68251876Speter
69251876Speter    sleeprate = 1000000/PRODUCER_ACTIVITY;
70251876Speter    apr_sleep((rand() % 4) * 1000000); /* sleep random seconds */
71251876Speter
72251876Speter    while (1)
73251876Speter    {
74251876Speter        rv = apr_queue_push(queue, NULL);
75251876Speter
76251876Speter        if (rv == APR_EINTR)
77251876Speter            continue;
78251876Speter
79251876Speter        if (rv == APR_EOF)
80251876Speter            break;
81251876Speter
82251876Speter        ABTS_TRUE(tc, rv == APR_SUCCESS);
83251876Speter
84251876Speter        apr_sleep(sleeprate); /* sleep this long to acheive our rate */
85251876Speter    }
86251876Speter
87251876Speter    return NULL;
88251876Speter}
89251876Speter
90251876Speterstatic void test_queue_producer_consumer(abts_case *tc, void *data)
91251876Speter{
92251876Speter    unsigned int i;
93251876Speter    apr_status_t rv;
94251876Speter    apr_thread_pool_t *thrp;
95251876Speter
96251876Speter    /* XXX: non-portable */
97251876Speter    srand((unsigned int)apr_time_now());
98251876Speter
99251876Speter    rv = apr_queue_create(&queue, QUEUE_SIZE, p);
100251876Speter    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
101251876Speter
102251876Speter    rv = apr_thread_pool_create(&thrp, 0, NUMBER_CONSUMERS + NUMBER_PRODUCERS, p);
103251876Speter    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
104251876Speter
105251876Speter    for (i = 0; i < NUMBER_CONSUMERS; i++) {
106251876Speter        rv = apr_thread_pool_push(thrp, consumer, tc, 0, NULL);
107251876Speter        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
108251876Speter    }
109251876Speter
110251876Speter    for (i = 0; i < NUMBER_PRODUCERS; i++) {
111251876Speter        rv = apr_thread_pool_push(thrp, producer, tc, 0, NULL);
112251876Speter        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
113251876Speter    }
114251876Speter
115251876Speter    apr_sleep(5000000); /* sleep 5 seconds */
116251876Speter
117251876Speter    rv = apr_queue_term(queue);
118251876Speter    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
119251876Speter
120251876Speter    rv = apr_thread_pool_destroy(thrp);
121251876Speter    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
122251876Speter}
123251876Speter
124251876Speter#endif /* APR_HAS_THREADS */
125251876Speter
126251876Speterabts_suite *testqueue(abts_suite *suite)
127251876Speter{
128251876Speter    suite = ADD_SUITE(suite);
129251876Speter
130251876Speter#if APR_HAS_THREADS
131251876Speter    abts_run_test(suite, test_queue_producer_consumer, NULL);
132251876Speter#endif /* APR_HAS_THREADS */
133251876Speter
134251876Speter    return suite;
135251876Speter}
136