2
// Multi-threaded magic squares server
3
// Runs as CGI (not multi-threaded) or multi-threaded standalone
4
// Computation of the magic square has been deliberately slowed down to
5
// demonstrate work load issues (see SLEEP constant)
7
// Run from the command line with arguments IP (which must be the
8
// IP of the current machine you are using) and PORT to run this as a
9
// multi-threaded stand-alone server on a port. For example:
10
// > mtmagicserver.cgi 18081
11
// To let 'magic' client talk to this service, change the URL in code magic.cpp
12
// into "localhost:18081"
14
// This example illustrates two alternative server implementations with threads.
15
// The first implementation recycles gSOAP resources but is bounded to a maximum
16
// number of threads. Each thread needs to be joined, so runaway processes will
17
// halt the server at some point.
18
// The second implementation has no thread limitation. Runaway threads are not
22
#include "magic.nsmap"
23
#include <unistd.h> // import sleep()
26
#define BACKLOG (100) // Max. request backlog
27
#define MAX_THR (8) // Max. threads to serve requests
28
#define SLEEP (0) // use this to make each thread sleep to mimic work load latency
30
////////////////////////////////////////////////////////////////////////////////
32
// Multi-Threaded Magic Squares Server
34
////////////////////////////////////////////////////////////////////////////////
36
void *process_request(void*);
38
int main(int argc, char **argv)
41
// soap.accept_timeout = 60; // die if no requests are made within 1 minute
42
if (argc < 2) // no args: assume this is a CGI application
43
{ soap_serve(&soap); // serve request
44
soap_destroy(&soap);// cleanup class instances
45
soap_end(&soap); // cleanup
52
m = soap_bind(&soap, NULL, port, BACKLOG);
54
{ soap_print_fault(&soap, stderr);
57
fprintf(stderr, "Socket connection successful %d\n", m);
59
{ s = soap_accept(&soap);
62
soap_print_fault(&soap, stderr);
64
fprintf(stderr, "Server timed out\n");
67
fprintf(stderr, "Thread %d accepts socket %d connection from IP %d.%d.%d.%d\n", i, s, (int)(soap.ip>>24)&0xFF, (int)(soap.ip>>16)&0xFF, (int)(soap.ip>>8)&0xFF, (int)soap.ip&0xFF);
68
pthread_create(&tid, NULL, (void*(*)(void*))process_request, (void*)soap_copy(&soap));
75
void *process_request(void *soap)
76
{ pthread_detach(pthread_self());
77
soap_serve((struct soap*)soap);
78
soap_destroy((struct soap*)soap);
79
soap_end((struct soap*)soap);
80
soap_done((struct soap*)soap);
85
////////////////////////////////////////////////////////////////////////////////
87
// Magic Square Algorithm
89
////////////////////////////////////////////////////////////////////////////////
91
int ns1__magic(struct soap *soap, int n, matrix *square)
92
{ int i, j, k, l, key = 2;
94
return soap_sender_fault(soap, "Negative or zero size", "<error xmlns=\"http://tempuri.org/\">The input parameter must be positive</error>");
96
return soap_sender_fault(soap, "size > 100", "<error xmlns=\"http://tempuri.org/\">The input parameter must not be too large</error>");
98
for (i = 0; i < n; i++)
99
for (j = 0; j < n; j++)
119
(*square)[i][j] = key;
122
sleep(SLEEP); // mimic work load latency
126
////////////////////////////////////////////////////////////////////////////////
128
// Class vector Methods
130
////////////////////////////////////////////////////////////////////////////////
137
vector::vector(int n)
138
{ __ptr = (int*)soap_malloc(soap, n*sizeof(int));
143
{ soap_unlink(soap, this); // not required, but just to make sure if someone calls delete on this
146
void vector::resize(int n)
150
p = (int*)soap_malloc(soap, n*sizeof(int));
152
{ for (int i = 0; i < (n <= __size ? n : __size); i++)
154
soap_unlink(soap, __ptr);
161
int& vector::operator[](int i) const
162
{ if (!__ptr || i < 0 || i >= __size)
163
fprintf(stderr, "Array index out of bounds\n");
167
////////////////////////////////////////////////////////////////////////////////
169
// Class matrix Methods
171
////////////////////////////////////////////////////////////////////////////////
178
matrix::matrix(int rows, int cols)
179
{ __ptr = soap_new_vector(soap, rows);
180
for (int i = 0; i < cols; i++)
181
__ptr[i].resize(cols);
186
{ soap_unlink(soap, this); // not required, but just to make sure if someone calls delete on this
189
void matrix::resize(int rows, int cols)
194
{ p = soap_new_vector(soap, rows);
195
for (i = 0; i < (rows <= __size ? rows : __size); i++)
196
{ if (this[i].__size != cols)
197
(*this)[i].resize(cols);
198
(p+i)->__ptr = __ptr[i].__ptr;
199
(p+i)->__size = cols;
201
for (; i < rows; i++)
202
__ptr[i].resize(cols);
205
{ __ptr = soap_new_vector(soap, rows);
206
for (i = 0; i < rows; i++)
207
__ptr[i].resize(cols);
212
for (i = 0; i < __size; i++)
213
__ptr[i].resize(cols);
216
vector& matrix::operator[](int i) const
217
{ if (!__ptr || i < 0 || i >= __size)
218
fprintf(stderr, "Array index out of bounds\n");