summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjcej <jcej@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1999-02-14 19:29:11 +0000
committerjcej <jcej@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1999-02-14 19:29:11 +0000
commit2e223ec826333dcedd350bd3df4f7a7e1e9161f2 (patch)
tree893c8b286dfae9b29b34d22dfd256a95ee2fcf8f
parent33864ee7505873b3bc93d5d40b9aad7fc17d4888 (diff)
downloadATCD-2e223ec826333dcedd350bd3df4f7a7e1e9161f2.tar.gz
*** empty log message ***
-rw-r--r--ChangeLog-99b21
-rw-r--r--docs/tutorials/015/Compressor.cpp7
-rw-r--r--docs/tutorials/015/Compressor.h9
-rw-r--r--docs/tutorials/015/Crypt.cpp4
-rw-r--r--docs/tutorials/015/Crypt.h4
-rw-r--r--docs/tutorials/015/Handler.cpp12
-rw-r--r--docs/tutorials/015/Protocol_Stream.cpp14
-rw-r--r--docs/tutorials/015/Protocol_Task.cpp85
-rw-r--r--docs/tutorials/015/Protocol_Task.h22
-rw-r--r--docs/tutorials/015/Recv.cpp8
-rw-r--r--docs/tutorials/015/Server_i.cpp1
-rw-r--r--docs/tutorials/015/Xmit.cpp2
-rw-r--r--docs/tutorials/015/combine.shar27
-rw-r--r--docs/tutorials/015/page01.html11
-rw-r--r--docs/tutorials/015/page05.html24
-rw-r--r--docs/tutorials/015/page07.html1
-rw-r--r--docs/tutorials/015/page09.html12
-rw-r--r--docs/tutorials/015/page11.html14
-rw-r--r--docs/tutorials/015/page12.html22
-rw-r--r--docs/tutorials/015/page13.html85
-rw-r--r--docs/tutorials/015/page15.html2
-rw-r--r--docs/tutorials/015/page17.html8
-rw-r--r--docs/tutorials/015/page18.html9
-rw-r--r--docs/tutorials/015/page19.html7
-rw-r--r--docs/tutorials/015/page20.html4
-rw-r--r--docs/tutorials/015/page21.html4
-rw-r--r--docs/tutorials/015/server.cpp24
-rw-r--r--docs/tutorials/016/Condition_i.h2
-rw-r--r--docs/tutorials/016/combine.shar103
-rw-r--r--docs/tutorials/016/condition.cpp38
-rw-r--r--docs/tutorials/016/page01.html53
-rw-r--r--docs/tutorials/016/page02.html2
-rw-r--r--docs/tutorials/016/page04.html38
-rw-r--r--docs/tutorials/017/combine.shar58
-rw-r--r--docs/tutorials/017/page01.html16
35 files changed, 397 insertions, 356 deletions
diff --git a/ChangeLog-99b b/ChangeLog-99b
index 6acf4f33134..8175dc351bf 100644
--- a/ChangeLog-99b
+++ b/ChangeLog-99b
@@ -1,3 +1,24 @@
+Sun Feb 14 14:09:11 1999 James CE Johnson <jcej@chiroptera.tragus.org>
+
+ * docs/tutorials/015/server.cpp (main): Force the singleton to use
+ the Select Reactor instead of the OS-default. This should fix the
+ problem this tutorial has on Win32 due to blocking vs non-blocking
+ socket configuration.
+
+ * docs/tutorials/015/Protocol_Task.h : Removed the ability to
+ activate this task. The code is now a little simpler and less
+ likely to behave in unpredicatable ways.
+
+ * docs/tutorials/015/* : A few typos fixed but mostly fallout from
+ removing the ability to activate the Protocol_Task.
+
+ * docs/tutorials/016/page01.html : Added Kirthika's abstract.
+
+ * docs/tutorials/016/condition.cpp : Made max_threads_ a
+ non-static member variable that is set by open().
+
+ * docs/tutorials/017/page01.html : Added Kirthika's abstract.
+
Sun Feb 14 12:47:03 1999 Carlos O'Ryan <coryan@cs.wustl.edu>
* ace/CDR_Stream.h:
diff --git a/docs/tutorials/015/Compressor.cpp b/docs/tutorials/015/Compressor.cpp
index f93d44009de..931264d716c 100644
--- a/docs/tutorials/015/Compressor.cpp
+++ b/docs/tutorials/015/Compressor.cpp
@@ -4,11 +4,8 @@
#include "Compressor.h"
#include "ace/SOCK_Stream.h"
-/* Construct our baseclass with the proper thread count. I really
- should remove this option...
- */
-Compressor::Compressor( int _thr_count )
- : Protocol_Task(_thr_count)
+Compressor::Compressor( void )
+ : Protocol_Task()
{
;
}
diff --git a/docs/tutorials/015/Compressor.h b/docs/tutorials/015/Compressor.h
index b822c6be59c..cb4c7248cce 100644
--- a/docs/tutorials/015/Compressor.h
+++ b/docs/tutorials/015/Compressor.h
@@ -14,14 +14,7 @@ public:
typedef Protocol_Task inherited;
- // I've given you the option of creating this task derivative
- // with a number of threads. In retro-spect that really isn't
- // a good idea. Most client/server systems rely on requests
- // and responses happening in a predicatable order. Introduce
- // a thread pool and message queue and that ordering goes
- // right out the window. In other words: Don't ever use the
- // constructor parameter!
- Compressor (int thr_count = 0);
+ Compressor (void);
~Compressor (void);
diff --git a/docs/tutorials/015/Crypt.cpp b/docs/tutorials/015/Crypt.cpp
index 1967bbe0ff1..83cfd7ab73f 100644
--- a/docs/tutorials/015/Crypt.cpp
+++ b/docs/tutorials/015/Crypt.cpp
@@ -6,8 +6,8 @@
/* The expected constructor...
*/
-Crypt::Crypt( int _thr_count )
- : Protocol_Task(_thr_count)
+Crypt::Crypt( void )
+ : Protocol_Task()
{
}
diff --git a/docs/tutorials/015/Crypt.h b/docs/tutorials/015/Crypt.h
index 60aa82f69bd..6de997fa4a9 100644
--- a/docs/tutorials/015/Crypt.h
+++ b/docs/tutorials/015/Crypt.h
@@ -14,9 +14,7 @@ public:
typedef Protocol_Task inherited;
- // Again we have the option of multiple threads and again I
- // regret tempting folks to use it.
- Crypt (int thr_count = 0);
+ Crypt (void);
~Crypt (void);
diff --git a/docs/tutorials/015/Handler.cpp b/docs/tutorials/015/Handler.cpp
index ab141c7e8c2..0cfb3242c3d 100644
--- a/docs/tutorials/015/Handler.cpp
+++ b/docs/tutorials/015/Handler.cpp
@@ -54,7 +54,7 @@ int Handler::open (void *)
// will prevent communicating with the client. This is
// something you'll want to do in every event handler you create.
if (this->peer ().get_remote_addr (addr) == -1)
- ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) can't get remote addr\n"), -1);
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) Cannot get remote addr\n"), -1);
// Announce the client
ACE_DEBUG ((LM_DEBUG, "(%P|%t) connected with %s\n", addr.get_host_name() ));
@@ -72,7 +72,7 @@ int Handler::open (void *)
// stream's open() may fail.
if( rval == -1 )
{
- ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) can't open the protocol stream.\n"), -1);
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) Cannot open the protocol stream.\n"), -1);
}
// Now that we know the client is valid and that the stream is
@@ -80,7 +80,7 @@ int Handler::open (void *)
// instance. Here again is an opportunity for improvement if
// we expect to have mulitple Server object instances.
if (ACE_Reactor::instance()->register_handler (this, ACE_Event_Handler::READ_MASK) == -1)
- ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) can't register with reactor\n"), -1);
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) Cannot register with reactor\n"), -1);
return rval;
}
@@ -125,7 +125,7 @@ int Handler::handle_input (ACE_HANDLE)
// will then be pushed through the protocol stream.
if( stream().get( ) == -1 )
{
- ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) can't get data from protocol stream\n"), -1);
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P|%t) Cannot get data from protocol stream\n"), -1);
}
return 0;
@@ -138,10 +138,10 @@ int Handler::handle_input (ACE_HANDLE)
several peers, however, you're probably just wasting a thread to
activate it. On the other hand, if your reactor is running in a
single thread (as in this example) then you can easily implement
- thread-per-connectin concurrency by giving the baseclass one thread.
+ thread-per-connection concurrency by giving the baseclass one thread.
*/
Handler_Task::Handler_Task(void)
- : inherited(0)
+ : inherited()
{
;
}
diff --git a/docs/tutorials/015/Protocol_Stream.cpp b/docs/tutorials/015/Protocol_Stream.cpp
index c82ab12335c..ed9b866a1bd 100644
--- a/docs/tutorials/015/Protocol_Stream.cpp
+++ b/docs/tutorials/015/Protocol_Stream.cpp
@@ -21,6 +21,16 @@
typedef ACE_Module<ACE_MT_SYNCH> Module;
typedef ACE_Thru_Task<ACE_MT_SYNCH> Thru_Task;
+/* An ACE_Stream is a collection of ACE_Modules. You can think of it
+ as a doubly-linked list if you like. Each Module contains two
+ ACE_Task derivatives. One of these tasks is used when sending data
+ "upstream", the other is used for "downstream" operation. In some
+ cases, you'll only need to move data in one direction. To provide
+ a placeholder for the other direction, ACE_Thru_Task can be used.
+ ACE_Thru_Task responds to the put() by simply invoking put_next()
+ to send the data to the next module.
+ */
+
/* Do-nothing constructor and destructor
*/
@@ -47,14 +57,14 @@ Protocol_Stream::open (ACE_SOCK_Stream &peer,
// Construct (and remember) the Recv object so that we can read from
// the peer().
ACE_NEW_RETURN (recv_,
- Recv (peer ()),
+ Recv ( this->peer ()),
-1);
// Add the transmit and receive tasks to the head of the stream. As
// we add more modules these will get pushed downstream and end up
// nearest the tail by the time we're done.
if (stream ().push (new Module ("Xmit/Recv",
- new Xmit (peer ()),
+ new Xmit ( this->peer ()),
recv_)) == -1)
ACE_ERROR_RETURN ((LM_ERROR,
"%p\n",
diff --git a/docs/tutorials/015/Protocol_Task.cpp b/docs/tutorials/015/Protocol_Task.cpp
index 3cfe7495539..b1eb82a43ad 100644
--- a/docs/tutorials/015/Protocol_Task.cpp
+++ b/docs/tutorials/015/Protocol_Task.cpp
@@ -4,113 +4,40 @@
#include "Protocol_Task.h"
// Construct the object and remember the thread count.
-Protocol_Task::Protocol_Task( int _thr_count )
- : desired_thr_count_(_thr_count)
+Protocol_Task::Protocol_Task(void)
{
+ ;
}
Protocol_Task::~Protocol_Task(void)
{
+ ;
}
-// Activate the object if necessary.
int Protocol_Task::open(void *arg)
{
ACE_UNUSED_ARG(arg);
- if( desired_thr_count_ )
- {
- return this->activate(THR_NEW_LWP, desired_thr_count_);
- }
-
return(0);
}
-/* When we're being closed by the ACE_Stream and we've got threads to
- worry about then we drop a hangup message onto the message queue so
- that svc() will go away. Except for the call to is_active(), this
- is lifted directly from Tutorial 14.
-*/
int Protocol_Task::close(u_long flags)
{
- if (flags == 1 && is_active() )
- {
- ACE_Message_Block *hangupBlock = new ACE_Message_Block();
-
- hangupBlock->msg_type(ACE_Message_Block::MB_HANGUP);
-
- if (this->putq(hangupBlock->duplicate()) == -1) {
- ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "Task::close() putq"), -1);
- }
-
- hangupBlock->release();
-
- return this->wait();
- }
-
return 0;
}
-/* The put() method has to make a decision. If we've got threads then
- put the unit of work onto the message queue for svc() to deal
- with. If not then process() it directly.
+/* When a message is put() onto the task, it's time to process() some data.
*/
int Protocol_Task::put(ACE_Message_Block *message,ACE_Time_Value *timeout)
{
- if( is_active() )
- {
- return this->putq(message,timeout);
- }
-
return this->process(message,timeout);
}
-/* svc() is about what you would expect. This is again lifted
- directly from Tutorial 14 but with a call to process() for handling
- the logic instead of doing the work right here.
+/* Return an error since we don't want the task to ever be activated.
*/
int Protocol_Task::svc(void)
{
- ACE_Message_Block * message;
-
- while (1)
- {
- // Get a message
- if ( this->getq(message, 0) == -1) {
- ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "Protocol_Task::svc() getq"), -1);
- }
-
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Protocol_Task::svc() got message\n"));
-
- // Check for hangup
- if (message->msg_type() == ACE_Message_Block::MB_HANGUP) {
-
- ACE_DEBUG ((LM_DEBUG, "(%P|%t) Protocol_Task::svc() -- HANGUP block received\n"));
-
- // Hangup our thread-pool peers (if any)
- if (this->putq(message->duplicate()) == -1) {
- ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "Protocol_Task::svc() putq"), -1);
- }
-
- // Leave svc()
- break;
- }
-
- // Do some work on the data.
- if( this->process(message->duplicate(),0) == -1 )
- {
- break;
- }
-
- // Give up the message block before we go get another.
- message->release();
- }
-
- // Give up the message block that caused us to exit the
- // while(1) loop.
- message->release();
-
- return(0);
+ return -1;
}
/* There's nothing really magic about process(). We just decide if
diff --git a/docs/tutorials/015/Protocol_Task.h b/docs/tutorials/015/Protocol_Task.h
index 993cebb2e89..f886001678f 100644
--- a/docs/tutorials/015/Protocol_Task.h
+++ b/docs/tutorials/015/Protocol_Task.h
@@ -10,18 +10,16 @@
#endif /* ACE_LACKS_PRAGMA_ONCE */
/* A typical ACE_Task<> derivative that adds a few things appropriate
- to protocol stacks.
+ to protocol stacks. To keep things a little simpler, we prevent
+ activation of the task and just borrow the thread of control from
+ the calling method in all cases.
*/
class Protocol_Task : public ACE_Task<ACE_MT_SYNCH>
{
public:
typedef ACE_Task<ACE_MT_SYNCH> inherited;
- // A choice of concurrency strategies is offered by the constructor.
- // In most cases it makes sense to set this to zero and let things
- // proceed serially. You might have a need, however, for some of
- // your tasks to have their own thread.
- Protocol_Task (int thr_count);
+ Protocol_Task (void);
~Protocol_Task (void);
@@ -37,8 +35,8 @@ public:
virtual int put (ACE_Message_Block *message,
ACE_Time_Value *timeout);
- // If you choose to activate the task then this method will be doing
- // all of the work.
+ // We're obligated to provide this signature even though we won't be
+ // allowing this object to be activated.
virtual int svc (void);
protected:
@@ -47,12 +45,6 @@ protected:
int process (ACE_Message_Block *message,
ACE_Time_Value *timeout);
- // Just let us know if we're active or not.
- int is_active (void)
- {
- return this->thr_count () != 0;
- }
-
// Tasks on the writer (downstream) side of the stream are called
// upon to send() data that will ultimately go to the peer.
virtual int send (ACE_Message_Block *message,
@@ -63,8 +55,6 @@ protected:
virtual int recv (ACE_Message_Block *message,
ACE_Time_Value *timeout);
-private:
- int desired_thr_count_;
};
#endif /* PROTOCOL_TASK_H */
diff --git a/docs/tutorials/015/Recv.cpp b/docs/tutorials/015/Recv.cpp
index 246968ddbf4..121e50c213b 100644
--- a/docs/tutorials/015/Recv.cpp
+++ b/docs/tutorials/015/Recv.cpp
@@ -8,7 +8,7 @@
initializations.
*/
Recv::Recv( ACE_SOCK_Stream & _peer )
- : Protocol_Task(0), peer_(_peer), error_(0)
+ : Protocol_Task(), peer_(_peer), error_(0)
{
// Create the tickler that get() will use to trigger recv()
// through the baseclass. Since we're single-threaded this is
@@ -47,7 +47,7 @@ int Recv::recv(ACE_Message_Block * message, ACE_Time_Value *timeout)
int b = 0;
/* Read from the socket one byte at a time until we see then
- end-of-string NULL character. Since the OS layers (at leas
+ end-of-string NULL character. Since the OS layers (at least
in Unix) will provide some buffering this isn't as bad as
it may seem at first.
@@ -55,7 +55,9 @@ int Recv::recv(ACE_Message_Block * message, ACE_Time_Value *timeout)
WFMO_Reactor is used. This is because the socket has been
placed into non-blocking mode and only the recv() of the
first byte will block. The solution is to use
- ACE_Select_Reactor and I hope to implement that soon.
+ ACE_Select_Reactor which doesn't change the socket
+ characteristics. We did that back in main(), so we should
+ be in good shape now.
*/
do
{
diff --git a/docs/tutorials/015/Server_i.cpp b/docs/tutorials/015/Server_i.cpp
index 5f8303f9919..e71803b3d26 100644
--- a/docs/tutorials/015/Server_i.cpp
+++ b/docs/tutorials/015/Server_i.cpp
@@ -70,5 +70,6 @@ int Server::run(void)
int Server::close(void)
{
finished_ = 1;
+ ACE_Reactor::instance()->notify();
return(0);
}
diff --git a/docs/tutorials/015/Xmit.cpp b/docs/tutorials/015/Xmit.cpp
index 28cc7055ce6..9450fc00cf0 100644
--- a/docs/tutorials/015/Xmit.cpp
+++ b/docs/tutorials/015/Xmit.cpp
@@ -12,7 +12,7 @@
cause more trouble than you want to deal with.
*/
Xmit::Xmit( ACE_SOCK_Stream & _peer )
- : Protocol_Task(0), peer_(_peer)
+ : Protocol_Task(), peer_(_peer)
{
}
diff --git a/docs/tutorials/015/combine.shar b/docs/tutorials/015/combine.shar
index b8fe561dd48..68a509ce351 100644
--- a/docs/tutorials/015/combine.shar
+++ b/docs/tutorials/015/combine.shar
@@ -3,7 +3,7 @@
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
-# Made on 1999-02-10 22:34 EST by <jcej@chiroptera.tragus.org>.
+# Made on 1999-02-14 13:38 EST by <jcej@chiroptera.tragus.org>.
# Source directory was `/var/home/jcej/projects/ACE_wrappers/docs/tutorials/015'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
@@ -13,7 +13,7 @@
# ------ ---------- ------------------------------------------
# 414 -rw-rw-r-- hdr
# 419 -rw-rw-r-- bodies
-# 4303 -rw-rw-r-- page01.pre
+# 4228 -rw-rw-r-- page01.pre
# 194 -rw-rw-r-- page02.pre
# 318 -rw-rw-r-- page03.pre
# 178 -rw-rw-r-- page04.pre
@@ -83,7 +83,7 @@ else
fi
rm -f 1231235999 $$.touch
#
-if mkdir _sh29164; then
+if mkdir _sh31334; then
$echo 'x -' 'creating lock directory'
else
$echo 'failed to create lock directory'
@@ -212,11 +212,12 @@ discussions.
<P>
Disclaimer:
<br>
-Several folks have reported problems with this tutorial on Win32. I
-have the fixes in mind but may not get them in place until 2/8 or so.
-What it amounts to is using the ACE_Select_Reactor for all platforms.
-Win32 defaults to ACE_WFMO_Reactor and that seems to be causing some
-or all of the problems.
+<ul>
+Several folks have reported problems with this tutorial on Win32.
+There are a couple of ways to solve this. I've chosen to solve it by
+using the ACE_Select_Reactor on all platforms instead of taking the
+OS-default.
+</ul>
<P>
Kirthika's abstract:
<UL>
@@ -277,19 +278,19 @@ etc.)
X compression objects. I'll leave that as a thought
X exercise!</font>
SHAR_EOF
- $shar_touch -am 0210223099 'page01.pre' &&
+ $shar_touch -am 0214124599 'page01.pre' &&
chmod 0664 'page01.pre' ||
$echo 'restore of' 'page01.pre' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'page01.pre:' 'MD5 check failed'
-77d3deec35fab659429a2eef4ab5b679 page01.pre
+a09c3ff1f21a90aab991e0f38dc00458 page01.pre
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`"
- test 4303 -eq "$shar_count" ||
- $echo 'page01.pre:' 'original size' '4303,' 'current size' "$shar_count!"
+ test 4228 -eq "$shar_count" ||
+ $echo 'page01.pre:' 'original size' '4228,' 'current size' "$shar_count!"
fi
fi
# ============= page02.pre ==============
@@ -1058,5 +1059,5 @@ SHAR_EOF
$echo 'page09.pst:' 'original size' '617,' 'current size' "$shar_count!"
fi
fi
-rm -fr _sh29164
+rm -fr _sh31334
exit 0
diff --git a/docs/tutorials/015/page01.html b/docs/tutorials/015/page01.html
index 40c62b39718..098d031d3ad 100644
--- a/docs/tutorials/015/page01.html
+++ b/docs/tutorials/015/page01.html
@@ -35,11 +35,12 @@ discussions.
<P>
Disclaimer:
<br>
-Several folks have reported problems with this tutorial on Win32. I
-have the fixes in mind but may not get them in place until 2/8 or so.
-What it amounts to is using the ACE_Select_Reactor for all platforms.
-Win32 defaults to ACE_WFMO_Reactor and that seems to be causing some
-or all of the problems.
+<ul>
+Several folks have reported problems with this tutorial on Win32.
+There are a couple of ways to solve this. I've chosen to solve it by
+using the ACE_Select_Reactor on all platforms instead of taking the
+OS-default.
+</ul>
<P>
Kirthika's abstract:
<UL>
diff --git a/docs/tutorials/015/page05.html b/docs/tutorials/015/page05.html
index d13aaa80476..eddb65d8579 100644
--- a/docs/tutorials/015/page05.html
+++ b/docs/tutorials/015/page05.html
@@ -24,6 +24,7 @@ simplification.
<font color=red>// $Id$</font>
<font color=blue>#include</font> "<font color=green>Server_i.h</font>"
+<font color=blue>#include</font> "<font color=green>ace/Select_Reactor.h</font>"
<font color=red>// A signal handler that will close the server object</font>
extern "<font color=green>C</font>" void handler (int)
@@ -33,7 +34,28 @@ extern "<font color=green>C</font>" void handler (int)
int main (int, char **)
{
- <font color=red>// The server object that abstracts away all of difficult parts.</font>
+ <font color=red>/* On Win32, the WFMO reactor is used by default.
+ Unfortunately, that causes the sockets to be put into
+ non-blocking mode which will break <font color=#008888>Recv::recv</font>(). To
+ prevent that issue, I explicitly use the Select Reactor
+ instead. I'll talk more about the "<font color=green>problem</font>" in the Recv
+ comments.
+ */</font>
+
+ <font color=red>// First, we create a Select_Reactor that will do the work.</font>
+ <font color=red>// To keep things simple, I'll create it on the stack.</font>
+ ACE_Select_Reactor mySelectReactor;
+
+ <font color=red>// Next, we need an ACE_Reactor that is the bridge between the </font>
+ <font color=red>// code and the real reactor. It is given a pointer to the</font>
+ <font color=red>// real reactor.</font>
+ ACE_Reactor myReactor (&mySelectReactor);
+
+ <font color=red>// Finally, we set the singleton instance to use the reactor</font>
+ <font color=red>// we've created.</font>
+ <font color=#008888>ACE_Reactor::instance</font> (&myReactor);
+
+ <font color=red>// The server object that abstracts away all of the difficult parts.</font>
Server server;
<font color=red>// Attempt to open the server. Like all good ACE-based</font>
diff --git a/docs/tutorials/015/page07.html b/docs/tutorials/015/page07.html
index 14f93a95731..06633974eb6 100644
--- a/docs/tutorials/015/page07.html
+++ b/docs/tutorials/015/page07.html
@@ -92,6 +92,7 @@ int <font color=#008888>Server::run</font>(void)
int <font color=#008888>Server::close</font>(void)
{
finished_ = 1;
+ <font color=#008888>ACE_Reactor::instance</font>()->notify();
return(0);
}
</PRE>
diff --git a/docs/tutorials/015/page09.html b/docs/tutorials/015/page09.html
index 558ba8ce8c3..b8156b13271 100644
--- a/docs/tutorials/015/page09.html
+++ b/docs/tutorials/015/page09.html
@@ -80,7 +80,7 @@ int <font color=#008888>Handler::open</font> (void *)
<font color=red>// will prevent communicating with the client. This is</font>
<font color=red>// something you'll want to do in every event handler you create.</font>
if (this->peer ().get_remote_addr (addr) == -1)
- ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) can't get remote addr\n</font>"), -1);
+ ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) Cannot get remote addr\n</font>"), -1);
<font color=red>// Announce the client</font>
ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) connected with %s\n</font>", addr.get_host_name() ));
@@ -98,7 +98,7 @@ int <font color=#008888>Handler::open</font> (void *)
<font color=red>// stream's open() may fail.</font>
if( rval == -1 )
{
- ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) can't open the protocol stream.\n</font>"), -1);
+ ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) Cannot open the protocol stream.\n</font>"), -1);
}
<font color=red>// Now that we know the client is valid and that the stream is </font>
@@ -106,7 +106,7 @@ int <font color=#008888>Handler::open</font> (void *)
<font color=red>// instance. Here again is an opportunity for improvement if</font>
<font color=red>// we expect to have mulitple Server object instances.</font>
if (<font color=#008888>ACE_Reactor::instance</font>()->register_handler (this, ACE_Event_Handler::READ_MASK) == -1)
- ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) can't register with reactor\n</font>"), -1);
+ ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) Cannot register with reactor\n</font>"), -1);
return rval;
}
@@ -151,7 +151,7 @@ int <font color=#008888>Handler::handle_input</font> (ACE_HANDLE)
<font color=red>// will then be pushed through the protocol stream.</font>
if( stream().get( ) == -1 )
{
- ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) can't get data from protocol stream\n</font>"), -1);
+ ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>(%P|%t) Cannot get data from protocol stream\n</font>"), -1);
}
return 0;
@@ -164,10 +164,10 @@ int <font color=#008888>Handler::handle_input</font> (ACE_HANDLE)
several peers, however, you're probably just wasting a thread to
activate it. On the other hand, if your reactor is running in a
single thread (as in this example) then you can easily implement
- thread-per-connectin concurrency by giving the baseclass one thread.
+ thread-per-connection concurrency by giving the baseclass one thread.
*/</font>
<font color=#008888>Handler_Task::Handler_Task</font>(void)
- : inherited(0)
+ : inherited()
{
;
}
diff --git a/docs/tutorials/015/page11.html b/docs/tutorials/015/page11.html
index f3225648a94..e03f1a5f7fe 100644
--- a/docs/tutorials/015/page11.html
+++ b/docs/tutorials/015/page11.html
@@ -42,6 +42,16 @@ concern in this file is to get everything in the correct order!
typedef ACE_Module&lt;ACE_MT_SYNCH> Module;
typedef ACE_Thru_Task&lt;ACE_MT_SYNCH> Thru_Task;
+<font color=red>/* An ACE_Stream is a collection of ACE_Modules. You can think of it
+ as a doubly-linked list if you like. Each Module contains two
+ ACE_Task derivatives. One of these tasks is used when sending data
+ "<font color=green>upstream</font>", the other is used for "<font color=green>downstream</font>" operation. In some
+ cases, you'll only need to move data in one direction. To provide
+ a placeholder for the other direction, ACE_Thru_Task can be used.
+ ACE_Thru_Task responds to the put() by simply invoking put_next()
+ to send the data to the next module.
+ */</font>
+
<font color=red>/* Do-nothing constructor and destructor
*/</font>
@@ -68,14 +78,14 @@ int
<font color=red>// Construct (and remember) the Recv object so that we can read from</font>
<font color=red>// the peer().</font>
ACE_NEW_RETURN (recv_,
- Recv (peer ()),
+ Recv ( this->peer ()),
-1);
<font color=red>// Add the transmit and receive tasks to the head of the stream. As</font>
<font color=red>// we add more modules these will get pushed downstream and end up</font>
<font color=red>// nearest the tail by the time we're done.</font>
if (stream ().push (new Module ("<font color=green>Xmit/Recv</font>",
- new Xmit (peer ()),
+ new Xmit ( this->peer ()),
recv_)) == -1)
ACE_ERROR_RETURN ((LM_ERROR,
"<font color=green>%p\n</font>",
diff --git a/docs/tutorials/015/page12.html b/docs/tutorials/015/page12.html
index 8dae49b5a18..07b36c3c9aa 100644
--- a/docs/tutorials/015/page12.html
+++ b/docs/tutorials/015/page12.html
@@ -27,18 +27,16 @@ A quick look at the Protocol_Task header...
<font color=blue>#endif</font> <font color=red>/* ACE_LACKS_PRAGMA_ONCE */</font>
<font color=red>/* A typical ACE_Task&lt;> derivative that adds a few things appropriate
- to protocol stacks.
+ to protocol stacks. To keep things a little simpler, we prevent
+ activation of the task and just borrow the thread of control from
+ the calling method in all cases.
*/</font>
class Protocol_Task : public ACE_Task&lt;ACE_MT_SYNCH>
{
public:
typedef ACE_Task&lt;ACE_MT_SYNCH> inherited;
- <font color=red>// A choice of concurrency strategies is offered by the constructor.</font>
- <font color=red>// In most cases it makes sense to set this to zero and let things</font>
- <font color=red>// proceed serially. You might have a need, however, for some of</font>
- <font color=red>// your tasks to have their own thread.</font>
- Protocol_Task (int thr_count);
+ Protocol_Task (void);
~Protocol_Task (void);
@@ -54,8 +52,8 @@ public:
virtual int put (ACE_Message_Block *message,
ACE_Time_Value *timeout);
- <font color=red>// If you choose to activate the task then this method will be doing</font>
- <font color=red>// all of the work.</font>
+ <font color=red>// We're obligated to provide this signature even though we won't be </font>
+ <font color=red>// allowing this object to be activated.</font>
virtual int svc (void);
protected:
@@ -64,12 +62,6 @@ protected:
int process (ACE_Message_Block *message,
ACE_Time_Value *timeout);
- <font color=red>// Just let us know if we're active or not.</font>
- int is_active (void)
- {
- return this->thr_count () != 0;
- }
-
<font color=red>// Tasks on the writer (downstream) side of the stream are called</font>
<font color=red>// upon to send() data that will ultimately go to the peer.</font>
virtual int send (ACE_Message_Block *message,
@@ -80,8 +72,6 @@ protected:
virtual int recv (ACE_Message_Block *message,
ACE_Time_Value *timeout);
-private:
- int desired_thr_count_;
};
<font color=blue>#endif</font> <font color=red>/* PROTOCOL_TASK_H */</font>
diff --git a/docs/tutorials/015/page13.html b/docs/tutorials/015/page13.html
index 967948e3d16..a6371dcc60a 100644
--- a/docs/tutorials/015/page13.html
+++ b/docs/tutorials/015/page13.html
@@ -25,113 +25,40 @@ only need one or two additional to do any real work.
<font color=blue>#include</font> "<font color=green>Protocol_Task.h</font>"
<font color=red>// Construct the object and remember the thread count.</font>
-<font color=#008888>Protocol_Task::Protocol_Task</font>( int _thr_count )
- : desired_thr_count_(_thr_count)
+<font color=#008888>Protocol_Task::Protocol_Task</font>(void)
{
+ ;
}
<font color=#008888>Protocol_Task::~Protocol_Task</font>(void)
{
+ ;
}
-<font color=red>// Activate the object if necessary.</font>
int <font color=#008888>Protocol_Task::open</font>(void *arg)
{
ACE_UNUSED_ARG(arg);
- if( desired_thr_count_ )
- {
- return this->activate(THR_NEW_LWP, desired_thr_count_);
- }
-
return(0);
}
-<font color=red>/* When we're being closed by the ACE_Stream and we've got threads to
- worry about then we drop a hangup message onto the message queue so
- that svc() will go away. Except for the call to is_active(), this
- is lifted directly from Tutorial 14.
-*/</font>
int <font color=#008888>Protocol_Task::close</font>(u_long flags)
{
- if (flags == 1 && is_active() )
- {
- ACE_Message_Block *hangupBlock = new ACE_Message_Block();
-
- hangupBlock->msg_type(<font color=#008888>ACE_Message_Block::MB_HANGUP</font>);
-
- if (this->putq(hangupBlock->duplicate()) == -1) {
- ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green><font color=#008888>Task::close</font>() putq</font>"), -1);
- }
-
- hangupBlock->release();
-
- return this->wait();
- }
-
return 0;
}
-<font color=red>/* The put() method has to make a decision. If we've got threads then
- put the unit of work onto the message queue for svc() to deal
- with. If not then process() it directly.
+<font color=red>/* When a message is put() onto the task, it's time to process() some data.
*/</font>
int <font color=#008888>Protocol_Task::put</font>(ACE_Message_Block *message,ACE_Time_Value *timeout)
{
- if( is_active() )
- {
- return this->putq(message,timeout);
- }
-
return this->process(message,timeout);
}
-<font color=red>/* svc() is about what you would expect. This is again lifted
- directly from Tutorial 14 but with a call to process() for handling
- the logic instead of doing the work right here.
+<font color=red>/* Return an error since we don't want the task to ever be activated.
*/</font>
int <font color=#008888>Protocol_Task::svc</font>(void)
{
- ACE_Message_Block * message;
-
- while (1)
- {
- <font color=red>// Get a message</font>
- if ( this->getq(message, 0) == -1) {
- ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green><font color=#008888>Protocol_Task::svc</font>() getq</font>"), -1);
- }
-
- ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) <font color=#008888>Protocol_Task::svc</font>() got message\n</font>"));
-
- <font color=red>// Check for hangup</font>
- if (message->msg_type() == <font color=#008888>ACE_Message_Block::MB_HANGUP</font>) {
-
- ACE_DEBUG ((LM_DEBUG, "<font color=green>(%P|%t) <font color=#008888>Protocol_Task::svc</font>() -- HANGUP block received\n</font>"));
-
- <font color=red>// Hangup our thread-pool peers (if any)</font>
- if (this->putq(message->duplicate()) == -1) {
- ACE_ERROR_RETURN ((LM_ERROR, "<font color=green>%p\n</font>", "<font color=green><font color=#008888>Protocol_Task::svc</font>() putq</font>"), -1);
- }
-
- <font color=red>// Leave svc()</font>
- break;
- }
-
- <font color=red>// Do some work on the data.</font>
- if( this->process(message->duplicate(),0) == -1 )
- {
- break;
- }
-
- <font color=red>// Give up the message block before we go get another.</font>
- message->release();
- }
-
- <font color=red>// Give up the message block that caused us to exit the</font>
- <font color=red>// while(1) loop.</font>
- message->release();
-
- return(0);
+ return -1;
}
<font color=red>/* There's nothing really magic about process(). We just decide if
diff --git a/docs/tutorials/015/page15.html b/docs/tutorials/015/page15.html
index d186b712daf..bcc7a7aa207 100644
--- a/docs/tutorials/015/page15.html
+++ b/docs/tutorials/015/page15.html
@@ -43,7 +43,7 @@ streams of data.
cause more trouble than you want to deal with.
*/</font>
<font color=#008888>Xmit::Xmit</font>( ACE_SOCK_Stream & _peer )
- : Protocol_Task(0), peer_(_peer)
+ : Protocol_Task(), peer_(_peer)
{
}
diff --git a/docs/tutorials/015/page17.html b/docs/tutorials/015/page17.html
index c45e4a6eeb8..625bf84110c 100644
--- a/docs/tutorials/015/page17.html
+++ b/docs/tutorials/015/page17.html
@@ -28,7 +28,7 @@ basic stuff.
initializations.
*/</font>
<font color=#008888>Recv::Recv</font>( ACE_SOCK_Stream & _peer )
- : Protocol_Task(0), peer_(_peer), error_(0)
+ : Protocol_Task(), peer_(_peer), error_(0)
{
<font color=red>// Create the tickler that get() will use to trigger recv()</font>
<font color=red>// through the baseclass. Since we're single-threaded this is</font>
@@ -67,7 +67,7 @@ int <font color=#008888>Recv::recv</font>(ACE_Message_Block * message, ACE_Time_
int b = 0;
<font color=red>/* Read from the socket one byte at a time until we see then
- end-of-string NULL character. Since the OS layers (at leas
+ end-of-string NULL character. Since the OS layers (at least
in Unix) will provide some buffering this isn't as bad as
it may seem at first.
@@ -75,7 +75,9 @@ int <font color=#008888>Recv::recv</font>(ACE_Message_Block * message, ACE_Time_
WFMO_Reactor is used. This is because the socket has been
placed into non-blocking mode and only the recv() of the
first byte will block. The solution is to use
- ACE_Select_Reactor and I hope to implement that soon.
+ ACE_Select_Reactor which doesn't change the socket
+ characteristics. We did that back in main(), so we should
+ be in good shape now.
*/</font>
do
{
diff --git a/docs/tutorials/015/page18.html b/docs/tutorials/015/page18.html
index c19a1559750..d17427ffeeb 100644
--- a/docs/tutorials/015/page18.html
+++ b/docs/tutorials/015/page18.html
@@ -36,14 +36,7 @@ public:
typedef Protocol_Task inherited;
- <font color=red>// I've given you the option of creating this task derivative</font>
- <font color=red>// with a number of threads. In retro-spect that really isn't</font>
- <font color=red>// a good idea. Most client/server systems rely on requests</font>
- <font color=red>// and responses happening in a predicatable order. Introduce</font>
- <font color=red>// a thread pool and message queue and that ordering goes</font>
- <font color=red>// right out the window. In other words: Don't ever use the</font>
- <font color=red>// constructor parameter!</font>
- Compressor (int thr_count = 0);
+ Compressor (void);
~Compressor (void);
diff --git a/docs/tutorials/015/page19.html b/docs/tutorials/015/page19.html
index 049bba13a06..e8689ebf9d7 100644
--- a/docs/tutorials/015/page19.html
+++ b/docs/tutorials/015/page19.html
@@ -24,11 +24,8 @@ things more difficult if something has to change in their interaction.
<font color=blue>#include</font> "<font color=green>Compressor.h</font>"
<font color=blue>#include</font> "<font color=green>ace/SOCK_Stream.h</font>"
-<font color=red>/* Construct our baseclass with the proper thread count. I really
- should remove this option...
- */</font>
-<font color=#008888>Compressor::Compressor</font>( int _thr_count )
- : Protocol_Task(_thr_count)
+<font color=#008888>Compressor::Compressor</font>( void )
+ : Protocol_Task()
{
;
}
diff --git a/docs/tutorials/015/page20.html b/docs/tutorials/015/page20.html
index 6b8917150e7..5a073600d10 100644
--- a/docs/tutorials/015/page20.html
+++ b/docs/tutorials/015/page20.html
@@ -37,9 +37,7 @@ public:
typedef Protocol_Task inherited;
- <font color=red>// Again we have the option of multiple threads and again I</font>
- <font color=red>// regret tempting folks to use it.</font>
- Crypt (int thr_count = 0);
+ Crypt (void);
~Crypt (void);
diff --git a/docs/tutorials/015/page21.html b/docs/tutorials/015/page21.html
index 5c7fc54eb27..951064b6922 100644
--- a/docs/tutorials/015/page21.html
+++ b/docs/tutorials/015/page21.html
@@ -25,8 +25,8 @@ favorite library.
<font color=red>/* The expected constructor...
*/</font>
-<font color=#008888>Crypt::Crypt</font>( int _thr_count )
- : Protocol_Task(_thr_count)
+<font color=#008888>Crypt::Crypt</font>( void )
+ : Protocol_Task()
{
}
diff --git a/docs/tutorials/015/server.cpp b/docs/tutorials/015/server.cpp
index bface44e341..4867833c220 100644
--- a/docs/tutorials/015/server.cpp
+++ b/docs/tutorials/015/server.cpp
@@ -2,6 +2,7 @@
// $Id$
#include "Server_i.h"
+#include "ace/Select_Reactor.h"
// A signal handler that will close the server object
extern "C" void handler (int)
@@ -11,7 +12,28 @@ extern "C" void handler (int)
int main (int, char **)
{
- // The server object that abstracts away all of difficult parts.
+ /* On Win32, the WFMO reactor is used by default.
+ Unfortunately, that causes the sockets to be put into
+ non-blocking mode which will break Recv::recv(). To
+ prevent that issue, I explicitly use the Select Reactor
+ instead. I'll talk more about the "problem" in the Recv
+ comments.
+ */
+
+ // First, we create a Select_Reactor that will do the work.
+ // To keep things simple, I'll create it on the stack.
+ ACE_Select_Reactor mySelectReactor;
+
+ // Next, we need an ACE_Reactor that is the bridge between the
+ // code and the real reactor. It is given a pointer to the
+ // real reactor.
+ ACE_Reactor myReactor (&mySelectReactor);
+
+ // Finally, we set the singleton instance to use the reactor
+ // we've created.
+ ACE_Reactor::instance (&myReactor);
+
+ // The server object that abstracts away all of the difficult parts.
Server server;
// Attempt to open the server. Like all good ACE-based
diff --git a/docs/tutorials/016/Condition_i.h b/docs/tutorials/016/Condition_i.h
index f1e5dad2bc1..2cd7adb21ba 100644
--- a/docs/tutorials/016/Condition_i.h
+++ b/docs/tutorials/016/Condition_i.h
@@ -12,7 +12,7 @@
threads - An ACE_Condition<> that enables blocking on state
changes in the variable The class I create here will contain those
three things. For the actual condition variable I've chosen an
- integer. You could easily turn this clas into a template
+ integer. You could easily turn this class into a template
parameterized on the condition variable's data type if 'int' isn't
what you want. */
class Condition
diff --git a/docs/tutorials/016/combine.shar b/docs/tutorials/016/combine.shar
index 503f70b83be..9c5c9d8c6c0 100644
--- a/docs/tutorials/016/combine.shar
+++ b/docs/tutorials/016/combine.shar
@@ -3,8 +3,8 @@
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
-# Made on 1998-10-29 15:09 EST by <jcej@caldera.lads.com>.
-# Source directory was `/scsiA/home/jcej/projects/ACE_wrappers/docs/tutorials/016'.
+# Made on 1999-02-14 14:20 EST by <jcej@chiroptera.tragus.org>.
+# Source directory was `/var/home/jcej/projects/ACE_wrappers/docs/tutorials/016'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
@@ -12,12 +12,12 @@
# length mode name
# ------ ---------- ------------------------------------------
# 422 -rw-rw-r-- hdr
-# 50 -rw-rw-r-- bodies
-# 789 -rw-rw-r-- page01.pre
-# 1350 -rw-rw-r-- page02.pre
+# 51 -rw-rw-r-- bodies
+# 2917 -rw-rw-r-- page01.pre
+# 1351 -rw-rw-r-- page02.pre
# 248 -rw-rw-r-- page03.pre
-# 309 -rw-rw-r-- page04.pre
-# 605 -rw-rw-r-- page05.pre
+# 310 -rw-rw-r-- page04.pre
+# 606 -rw-rw-r-- page05.pre
#
save_IFS="${IFS}"
IFS="${IFS}:"
@@ -64,7 +64,7 @@ else
fi
rm -f 1231235999 $$.touch
#
-if mkdir _sh03957; then
+if mkdir _sh31855; then
$echo 'x -' 'creating lock directory'
else
$echo 'failed to create lock directory'
@@ -124,12 +124,12 @@ SHAR_EOF
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'bodies:' 'MD5 check failed'
-06c11389b22b88d88110d2338c4dbaaf bodies
+53b96616ae101b38fd1e30b2ab8707a2 bodies
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`"
- test 50 -eq "$shar_count" ||
- $echo 'bodies:' 'original size' '50,' 'current size' "$shar_count!"
+ test 51 -eq "$shar_count" ||
+ $echo 'bodies:' 'original size' '51,' 'current size' "$shar_count!"
fi
fi
# ============= page01.pre ==============
@@ -153,20 +153,73 @@ In this tutorial, I'll create a wrapper class around the ACE_Condition
and the assorted housekeeping items necessary to make it work. I'll
use a simple integer as the condition variable but keep in mind that
you can use any data type you want.
+<P>
+Kirthika's abstract:
+<ul>
+An ACE_Condition class is a synchronisation mechanism employed in
+situations where one or more threads cannot access the shared resource
+unless some 'condition' becomes true. The ACE_Condition is associated
+with a Mutex-lock which is released before blocking internally in the
+wait call. Once the blocked thread is signaled to wake up again it
+internally re-acquires the lock before checking the condition.
+Unless the condition is true and it has the lock, it cant go ahead.
+Once the shared resource is freed, a signal is sent to the waiting
+threads which can now contend for the lock and access the resource.
+<P>
+Pizza-delivery metaphor: (courtesy Dr.Schmidt)
+<ul>
+Pizza delivery boy -- thread<br>
+keys to delivery van -- mutex-lock<br>
+pizza ready for delivery -- condition<br>
+</Ul>
+Situation: <br>
+<ul>
+Five pizza delivery boys use the same van. While the van is
+unavailable, the boys go to sleep. When the van returns and the keys
+are returned, the current user of the van nudges the other sleeping boys
+to wake up and fight for the keys. Once the keys are obtained and the
+pizza
+is ready and out of the kitchen, the boy with the pizza and the keys can
+now deliver it.
+</ul>
+<P>
+This tutorial makes use of a wrapper class around the ACE_Condition and
+uses a integer value as the condition. The four kinds of condition
+implemented
+are: !=, >=, <=, == by using C++ operator overloading. Guards are used
+within
+the methods to make sure that the method is thread-safe. Once the thread
+completes
+its job, it broadcasts to the waiting on it.
+<P>
+An ACE_Task is used to stress test the various conditions.
+A test object is created for each condition and the main thread waits
+until the condition becomes true. For instance: <= condition:
+Five threads are spwaned which in turn increment the condition
+variable, which is initialised to 1 by 2. Remember that you are waiting
+on
+the <= condition. So once 3 threads have been thru it, the value becomes
+6
+and the condition becomes true!
+<P>
+This simple example shows us how to program and use the Condition
+variable for
+synchronisation.
+</ul>
SHAR_EOF
- $shar_touch -am 1029153198 'page01.pre' &&
+ $shar_touch -am 0214140699 'page01.pre' &&
chmod 0664 'page01.pre' ||
$echo 'restore of' 'page01.pre' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'page01.pre:' 'MD5 check failed'
-aa9f5774f5415d7a430891e9296bfab0 page01.pre
+37032e8a180a426e2677f3c2848162bb page01.pre
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`"
- test 789 -eq "$shar_count" ||
- $echo 'page01.pre:' 'original size' '789,' 'current size' "$shar_count!"
+ test 2917 -eq "$shar_count" ||
+ $echo 'page01.pre:' 'original size' '2917,' 'current size' "$shar_count!"
fi
fi
# ============= page02.pre ==============
@@ -228,12 +281,12 @@ SHAR_EOF
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'page02.pre:' 'MD5 check failed'
-ccf4d7623038838df6249b5134827402 page02.pre
+d3230a58558843154d2363ce940dbb9b page02.pre
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`"
- test 1350 -eq "$shar_count" ||
- $echo 'page02.pre:' 'original size' '1350,' 'current size' "$shar_count!"
+ test 1351 -eq "$shar_count" ||
+ $echo 'page02.pre:' 'original size' '1351,' 'current size' "$shar_count!"
fi
fi
# ============= page03.pre ==============
@@ -283,12 +336,12 @@ SHAR_EOF
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'page04.pre:' 'MD5 check failed'
-b6694ddc18814a64feeb56f46ffd7d17 page04.pre
+a2b2c42216f88e006a18d37adcb31c1d page04.pre
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`"
- test 309 -eq "$shar_count" ||
- $echo 'page04.pre:' 'original size' '309,' 'current size' "$shar_count!"
+ test 310 -eq "$shar_count" ||
+ $echo 'page04.pre:' 'original size' '310,' 'current size' "$shar_count!"
fi
fi
# ============= page05.pre ==============
@@ -320,13 +373,13 @@ SHAR_EOF
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'page05.pre:' 'MD5 check failed'
-f63c4bfe37b1fe5785a6af9b204cb0bf page05.pre
+3926547773016bf56d809fae9170625e page05.pre
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page05.pre'`"
- test 605 -eq "$shar_count" ||
- $echo 'page05.pre:' 'original size' '605,' 'current size' "$shar_count!"
+ test 606 -eq "$shar_count" ||
+ $echo 'page05.pre:' 'original size' '606,' 'current size' "$shar_count!"
fi
fi
-rm -fr _sh03957
+rm -fr _sh31855
exit 0
diff --git a/docs/tutorials/016/condition.cpp b/docs/tutorials/016/condition.cpp
index 5ec772a4a7f..d489ee6a355 100644
--- a/docs/tutorials/016/condition.cpp
+++ b/docs/tutorials/016/condition.cpp
@@ -12,7 +12,7 @@ class Test : public ACE_Task<ACE_NULL_SYNCH>
{
public:
// Construct the condition variable with an initial value.
- Test( Condition::value_t _value );
+ Test( int _max_threads, Condition::value_t _value );
~Test(void);
// Open the Task with enough threads to make a useful test.
@@ -24,12 +24,13 @@ protected:
// Override this method to modify the Condition in some way.
virtual void modify(void) = 0;
+
// Override this to test the Condition in some way.
virtual void test(void) = 0;
// How many threads to use in the test. This is also used in the
// modify() and test() methods of the derivatives.
- static const int max_threads_;
+ int max_threads_;
// We want to sleep for a random amount of time to simulate
// work. The seed is necessary for proper random number generation.
@@ -39,12 +40,9 @@ protected:
Condition condition_;
};
-// Set the number of threads.
-const int Test::max_threads_ = 5;
-
// Initialize the condition variable.
-Test::Test( Condition::value_t _value )
- : condition_(_value)
+Test::Test( int _max_threads, Condition::value_t _value )
+ : max_threads_(_max_threads), condition_(_value)
{
;
}
@@ -99,8 +97,8 @@ class Test_ne : public Test
{
public:
// Initialize the condition variable to zero since we're counting up.
- Test_ne(void)
- : Test(0)
+ Test_ne( int _max_threads )
+ : Test(_max_threads,0)
{
ACE_DEBUG ((LM_INFO, "\n(%P|%t|%T)\tTesting condition_ != %d\n", max_threads_));
}
@@ -129,8 +127,8 @@ public:
// For max_threads_ == 5, we will start the condition variable at
// the value 9. When the "last" thread decrements it, the value
// will be 4 which satisfies the condition.
- Test_ge(void)
- : Test(max_threads_*2-1)
+ Test_ge( int _max_threads )
+ : Test(_max_threads,_max_threads*2-1)
{
ACE_DEBUG ((LM_INFO, "\n(%P|%t|%T)\tTesting condition_ >= %d\n", max_threads_));
}
@@ -159,8 +157,8 @@ public:
// I'm starting the value at 1 so that if we increment by one in
// each thread, the "last" thread (of 5) will set the value to
// 6. Since I actually increment by 2, we could start somewhat lower.
- Test_le(void)
- : Test(1)
+ Test_le( int _max_threads )
+ : Test( _max_threads, 1 )
{
ACE_DEBUG ((LM_INFO, "\n(%P|%t|%T)\tTesting condition_ <= %d\n", max_threads_));
}
@@ -188,8 +186,8 @@ class Test_fo : public Test
public:
// We'll be using operator*=(int) to increment the condition
// variable, so we need to start with a non-zero value.
- Test_fo(void)
- : Test(1)
+ Test_fo( int _max_threads )
+ : Test( _max_threads, 1 )
{
ACE_DEBUG ((LM_INFO, "\n(%P|%t|%T)\tTesting condition_ == FunctionObject\n" ));
}
@@ -209,6 +207,8 @@ public:
public:
// When this returns non-zero, the condition test operator
// will unblock in each thread.
+ // Note that 32 was chosen because 2**5 == 32. That is, the
+ // fifth thread will modify() the value to 32.
int operator() ( Condition::value_t _value )
{
return _value == 32;
@@ -229,19 +229,19 @@ public:
*/
int main(int, char **)
{
- Test_ne test_ne;
+ Test_ne test_ne(5);
test_ne.open();
test_ne.wait();
- Test_ge test_ge;
+ Test_ge test_ge(5);
test_ge.open();
test_ge.wait();
- Test_le test_le;
+ Test_le test_le(5);
test_le.open();
test_le.wait();
- Test_fo test_fo;
+ Test_fo test_fo(5);
test_fo.open();
test_fo.wait();
diff --git a/docs/tutorials/016/page01.html b/docs/tutorials/016/page01.html
index 057ca7142d9..8781d692e14 100644
--- a/docs/tutorials/016/page01.html
+++ b/docs/tutorials/016/page01.html
@@ -27,5 +27,58 @@ In this tutorial, I'll create a wrapper class around the ACE_Condition
and the assorted housekeeping items necessary to make it work. I'll
use a simple integer as the condition variable but keep in mind that
you can use any data type you want.
+<P>
+Kirthika's abstract:
+<ul>
+An ACE_Condition class is a synchronisation mechanism employed in
+situations where one or more threads cannot access the shared resource
+unless some 'condition' becomes true. The ACE_Condition is associated
+with a Mutex-lock which is released before blocking internally in the
+wait call. Once the blocked thread is signaled to wake up again it
+internally re-acquires the lock before checking the condition.
+Unless the condition is true and it has the lock, it cant go ahead.
+Once the shared resource is freed, a signal is sent to the waiting
+threads which can now contend for the lock and access the resource.
+<P>
+Pizza-delivery metaphor: (courtesy Dr.Schmidt)
+<ul>
+Pizza delivery boy -- thread<br>
+keys to delivery van -- mutex-lock<br>
+pizza ready for delivery -- condition<br>
+</Ul>
+Situation: <br>
+<ul>
+Five pizza delivery boys use the same van. While the van is
+unavailable, the boys go to sleep. When the van returns and the keys
+are returned, the current user of the van nudges the other sleeping boys
+to wake up and fight for the keys. Once the keys are obtained and the
+pizza
+is ready and out of the kitchen, the boy with the pizza and the keys can
+now deliver it.
+</ul>
+<P>
+This tutorial makes use of a wrapper class around the ACE_Condition and
+uses a integer value as the condition. The four kinds of condition
+implemented
+are: !=, >=, <=, == by using C++ operator overloading. Guards are used
+within
+the methods to make sure that the method is thread-safe. Once the thread
+completes
+its job, it broadcasts to the waiting on it.
+<P>
+An ACE_Task is used to stress test the various conditions.
+A test object is created for each condition and the main thread waits
+until the condition becomes true. For instance: <= condition:
+Five threads are spwaned which in turn increment the condition
+variable, which is initialised to 1 by 2. Remember that you are waiting
+on
+the <= condition. So once 3 threads have been thru it, the value becomes
+6
+and the condition becomes true!
+<P>
+This simple example shows us how to program and use the Condition
+variable for
+synchronisation.
+</ul>
<P><HR WIDTH="100%">
<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page02.html">Continue This Tutorial</A>]</CENTER>
diff --git a/docs/tutorials/016/page02.html b/docs/tutorials/016/page02.html
index 70e58f57e3f..bda581108e5 100644
--- a/docs/tutorials/016/page02.html
+++ b/docs/tutorials/016/page02.html
@@ -72,7 +72,7 @@ condition to occur.
threads - An ACE_Condition&lt;> that enables blocking on state
changes in the variable The class I create here will contain those
three things. For the actual condition variable I've chosen an
- integer. You could easily turn this clas into a template
+ integer. You could easily turn this class into a template
parameterized on the condition variable's data type if 'int' isn't
what you want. */</font>
class Condition
diff --git a/docs/tutorials/016/page04.html b/docs/tutorials/016/page04.html
index b94fe2e48af..654790d6594 100644
--- a/docs/tutorials/016/page04.html
+++ b/docs/tutorials/016/page04.html
@@ -33,7 +33,7 @@ class Test : public ACE_Task&lt;ACE_NULL_SYNCH>
{
public:
<font color=red>// Construct the condition variable with an initial value.</font>
- Test( <font color=#008888>Condition::value_t</font> _value );
+ Test( int _max_threads, <font color=#008888>Condition::value_t</font> _value );
~Test(void);
<font color=red>// Open the Task with enough threads to make a useful test.</font>
@@ -45,12 +45,13 @@ protected:
<font color=red>// Override this method to modify the Condition in some way.</font>
virtual void modify(void) = 0;
+
<font color=red>// Override this to test the Condition in some way.</font>
virtual void test(void) = 0;
<font color=red>// How many threads to use in the test. This is also used in the</font>
<font color=red>// modify() and test() methods of the derivatives.</font>
- static const int max_threads_;
+ int max_threads_;
<font color=red>// We want to sleep for a random amount of time to simulate</font>
<font color=red>// work. The seed is necessary for proper random number generation.</font>
@@ -60,12 +61,9 @@ protected:
Condition condition_;
};
-<font color=red>// Set the number of threads.</font>
-const int <font color=#008888>Test::max_threads_</font> = 5;
-
<font color=red>// Initialize the condition variable.</font>
-<font color=#008888>Test::Test</font>( Condition::value_t _value )
- : condition_(_value)
+<font color=#008888>Test::Test</font>( int _max_threads, Condition::value_t _value )
+ : max_threads_(_max_threads), condition_(_value)
{
;
}
@@ -120,8 +118,8 @@ class Test_ne : public Test
{
public:
<font color=red>// Initialize the condition variable to zero since we're counting up.</font>
- Test_ne(void)
- : Test(0)
+ Test_ne( int _max_threads )
+ : Test(_max_threads,0)
{
ACE_DEBUG ((LM_INFO, "<font color=green>\n(%P|%t|%T)\tTesting condition_ != %d\n</font>", max_threads_));
}
@@ -150,8 +148,8 @@ public:
<font color=red>// For max_threads_ == 5, we will start the condition variable at </font>
<font color=red>// the value 9. When the "<font color=green>last</font>" thread decrements it, the value</font>
<font color=red>// will be 4 which satisfies the condition.</font>
- Test_ge(void)
- : Test(max_threads_*2-1)
+ Test_ge( int _max_threads )
+ : Test(_max_threads,_max_threads*2-1)
{
ACE_DEBUG ((LM_INFO, "<font color=green>\n(%P|%t|%T)\tTesting condition_ >= %d\n</font>", max_threads_));
}
@@ -180,8 +178,8 @@ public:
<font color=red>// I'm starting the value at 1 so that if we increment by one in</font>
<font color=red>// each thread, the "<font color=green>last</font>" thread (of 5) will set the value to</font>
<font color=red>// 6. Since I actually increment by 2, we could start somewhat lower.</font>
- Test_le(void)
- : Test(1)
+ Test_le( int _max_threads )
+ : Test( _max_threads, 1 )
{
ACE_DEBUG ((LM_INFO, "<font color=green>\n(%P|%t|%T)\tTesting condition_ &lt;= %d\n</font>", max_threads_));
}
@@ -209,8 +207,8 @@ class Test_fo : public Test
public:
<font color=red>// We'll be using operator*=(int) to increment the condition</font>
<font color=red>// variable, so we need to start with a non-zero value.</font>
- Test_fo(void)
- : Test(1)
+ Test_fo( int _max_threads )
+ : Test( _max_threads, 1 )
{
ACE_DEBUG ((LM_INFO, "<font color=green>\n(%P|%t|%T)\tTesting condition_ == FunctionObject\n</font>" ));
}
@@ -230,6 +228,8 @@ public:
public:
<font color=red>// When this returns non-zero, the condition test operator</font>
<font color=red>// will unblock in each thread.</font>
+ <font color=red>// Note that 32 was chosen because 2**5 == 32. That is, the</font>
+ <font color=red>// fifth thread will modify() the value to 32.</font>
int operator() ( <font color=#008888>Condition::value_t</font> _value )
{
return _value == 32;
@@ -250,19 +250,19 @@ public:
*/</font>
int main(int, char **)
{
- Test_ne test_ne;
+ Test_ne test_ne(5);
test_ne.open();
test_ne.wait();
- Test_ge test_ge;
+ Test_ge test_ge(5);
test_ge.open();
test_ge.wait();
- Test_le test_le;
+ Test_le test_le(5);
test_le.open();
test_le.wait();
- Test_fo test_fo;
+ Test_fo test_fo(5);
test_fo.open();
test_fo.wait();
diff --git a/docs/tutorials/017/combine.shar b/docs/tutorials/017/combine.shar
index 7e826ed7928..ff6f7ef7d2d 100644
--- a/docs/tutorials/017/combine.shar
+++ b/docs/tutorials/017/combine.shar
@@ -3,8 +3,8 @@
# To extract the files from this archive, save it to some FILE, remove
# everything before the `!/bin/sh' line above, then type `sh FILE'.
#
-# Made on 1998-11-10 14:42 EST by <jcej@caldera.lads.com>.
-# Source directory was `/scsiA/home/jcej/projects/ACE_wrappers/docs/tutorials/017'.
+# Made on 1999-02-14 14:25 EST by <jcej@chiroptera.tragus.org>.
+# Source directory was `/var/home/jcej/projects/ACE_wrappers/docs/tutorials/017'.
#
# Existing files will *not* be overwritten unless `-c' is specified.
#
@@ -12,11 +12,11 @@
# length mode name
# ------ ---------- ------------------------------------------
# 422 -rw-rw-r-- hdr
-# 44 -rw-rw-r-- bodies
-# 843 -rw-rw-r-- page01.pre
-# 419 -rw-rw-r-- page02.pre
+# 45 -rw-rw-r-- bodies
+# 1397 -rw-rw-r-- page01.pre
+# 420 -rw-rw-r-- page02.pre
# 739 -rw-rw-r-- page03.pre
-# 478 -rw-rw-r-- page04.pre
+# 479 -rw-rw-r-- page04.pre
# 375 -rw-rw-r-- page05.pre
#
save_IFS="${IFS}"
@@ -64,7 +64,7 @@ else
fi
rm -f 1231235999 $$.touch
#
-if mkdir _sh01874; then
+if mkdir _sh32003; then
$echo 'x -' 'creating lock directory'
else
$echo 'failed to create lock directory'
@@ -124,12 +124,12 @@ SHAR_EOF
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'bodies:' 'MD5 check failed'
-1b7c57aab2c61f845219723b8558bea6 bodies
+4924294a77d6ba78dcf667e92c341b4f bodies
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'bodies'`"
- test 44 -eq "$shar_count" ||
- $echo 'bodies:' 'original size' '44,' 'current size' "$shar_count!"
+ test 45 -eq "$shar_count" ||
+ $echo 'bodies:' 'original size' '45,' 'current size' "$shar_count!"
fi
fi
# ============= page01.pre ==============
@@ -156,20 +156,36 @@ continuing.
In this tutorial I'll create a simple wrapper for the ACE_Barrier. In
reality, the ACE_Barrier is so easy that a wrapper isn't really
needed. I created the wrapper anyway though just because I wanted to.
+<P>
+Kirthika's abstract:
+<ul>
+The ACE_Barrier class is used for collective thread syncronisation. All
+the threads block at the barrier and advance only after everyone is at
+the
+barrier. A thread blocks by calling the wait() method and stays until
+all the other threads invoke wait() one-by-one at the barrier and then
+all
+move ahead.
+Here, an abstract barrier class is created which incorporates the
+ACE_Barrier
+mechanism and is used in a test case of an ACE_Task with 10 and 5
+threads respectively
+which illustrate the use of the barrier pattern.
+</ul>
SHAR_EOF
- $shar_touch -am 1110144198 'page01.pre' &&
+ $shar_touch -am 0214142599 'page01.pre' &&
chmod 0664 'page01.pre' ||
$echo 'restore of' 'page01.pre' 'failed'
if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'page01.pre:' 'MD5 check failed'
-30840e2b3e8bf84d94abb9177bffbbec page01.pre
+2c9cb9ca7f82997142a59a9324d5fe17 page01.pre
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page01.pre'`"
- test 843 -eq "$shar_count" ||
- $echo 'page01.pre:' 'original size' '843,' 'current size' "$shar_count!"
+ test 1397 -eq "$shar_count" ||
+ $echo 'page01.pre:' 'original size' '1397,' 'current size' "$shar_count!"
fi
fi
# ============= page02.pre ==============
@@ -195,12 +211,12 @@ SHAR_EOF
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'page02.pre:' 'MD5 check failed'
-72dd8d286e36d8911945824bf2c91cc3 page02.pre
+9e2b4b85abf1bff15b94b6d20bc20f91 page02.pre
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page02.pre'`"
- test 419 -eq "$shar_count" ||
- $echo 'page02.pre:' 'original size' '419,' 'current size' "$shar_count!"
+ test 420 -eq "$shar_count" ||
+ $echo 'page02.pre:' 'original size' '420,' 'current size' "$shar_count!"
fi
fi
# ============= page03.pre ==============
@@ -260,12 +276,12 @@ SHAR_EOF
&& ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
md5sum -c << SHAR_EOF >/dev/null 2>&1 \
|| $echo 'page04.pre:' 'MD5 check failed'
-bed05089cb64c075cceec277e2a7da5f page04.pre
+0c46b51370a57179cea56ef57fd0b1f4 page04.pre
SHAR_EOF
else
shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'page04.pre'`"
- test 478 -eq "$shar_count" ||
- $echo 'page04.pre:' 'original size' '478,' 'current size' "$shar_count!"
+ test 479 -eq "$shar_count" ||
+ $echo 'page04.pre:' 'original size' '479,' 'current size' "$shar_count!"
fi
fi
# ============= page05.pre ==============
@@ -300,5 +316,5 @@ SHAR_EOF
$echo 'page05.pre:' 'original size' '375,' 'current size' "$shar_count!"
fi
fi
-rm -fr _sh01874
+rm -fr _sh32003
exit 0
diff --git a/docs/tutorials/017/page01.html b/docs/tutorials/017/page01.html
index 5486ecbf66a..25d4c94ae02 100644
--- a/docs/tutorials/017/page01.html
+++ b/docs/tutorials/017/page01.html
@@ -30,5 +30,21 @@ continuing.
In this tutorial I'll create a simple wrapper for the ACE_Barrier. In
reality, the ACE_Barrier is so easy that a wrapper isn't really
needed. I created the wrapper anyway though just because I wanted to.
+<P>
+Kirthika's abstract:
+<ul>
+The ACE_Barrier class is used for collective thread syncronisation. All
+the threads block at the barrier and advance only after everyone is at
+the
+barrier. A thread blocks by calling the wait() method and stays until
+all the other threads invoke wait() one-by-one at the barrier and then
+all
+move ahead.
+Here, an abstract barrier class is created which incorporates the
+ACE_Barrier
+mechanism and is used in a test case of an ACE_Task with 10 and 5
+threads respectively
+which illustrate the use of the barrier pattern.
+</ul>
<P><HR WIDTH="100%">
<CENTER>[<A HREF="../online-tutorials.html">Tutorial Index</A>] [<A HREF="page02.html">Continue This Tutorial</A>]</CENTER>