CPN
Computational Process Networks
D4RQueue.cc
Go to the documentation of this file.
1 //=============================================================================
2 // Computational Process Networks class library
3 // Copyright (C) 1997-2006 Gregory E. Allen and The University of Texas
4 //
5 // This library is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU Library General Public License as published
7 // by the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Library General Public License for more details.
14 //
15 // The GNU Public License is available in the file LICENSE, or you
16 // can write to the Free Software Foundation, Inc., 59 Temple Place -
17 // Suite 330, Boston, MA 02111-1307, USA, or you can find it on the
18 // World Wide Web at http://www.fsf.org.
19 //=============================================================================
23 #include "common_priv.h"
24 #include <cpn/d4r/D4RQueue.h>
25 #include <cpn/d4r/D4RNode.h>
27 #include <cpn/utils/AutoLock.h>
28 #include <cpn/utils/AutoUnlock.h>
29 
30 #if D4RTRACE
31 #include <stdio.h>
32 #define DEBUG(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__)
33 #else
34 #define DEBUG(fmt, ...)
35 #endif
36 
37 template <typename T>
38 class ScopeSetter {
39 public:
40  ScopeSetter(T &val_, T set) : val(val_), old(val)
41  {
42  val = set;
43  }
44  ~ScopeSetter() { val = old; }
45  T &val;
46  T old;
47 };
48 
49 namespace D4R {
50 
52  : readtagchanged(false),
53  writetagchanged(false),
54  incomm(false)
55  {}
56 
58 
59  void QueueBase::SetReaderNode(shared_ptr<Node> n) {
60  AutoLock<QueueBase> al(*this);
61  reader = n;
62  Signal();
63  }
64 
65  void QueueBase::SetWriterNode(shared_ptr<Node> n) {
66  AutoLock<QueueBase> al(*this);
67  writer = n;
68  Signal();
69  }
70 
72  if (!writer) {
73  while (ReadBlocked() && !writer) {
74  Wait();
75  }
76  }
77  if (!ReadBlocked()) { return; }
78  writetagchanged = false;
79  try {
80  while (incomm) { Wait(); }
81  ScopeSetter<bool> ss(incomm, true);
82  AutoUnlock<QueueBase> au(*this);
83  reader->Block(writer->GetPublicTag(), -1);
84  } catch (...) { Signal(); throw; }
85  Signal();
86  while (ReadBlocked()) {
87  if (writetagchanged) {
88  writetagchanged = false;
89  bool detect;
90  try {
91  while (incomm) { Wait(); }
92  ScopeSetter<bool> ss(incomm, true);
93  AutoUnlock<QueueBase> au(*this);
94  detect = reader->Transmit(writer->GetPublicTag());
95  } catch (...) { Signal(); throw; }
96  Signal();
97  if (detect) {
98  throw DeadlockException("True deadlock detected");
99  }
100  } else {
101  Wait();
102  }
103  }
104  }
105 
106  void QueueBase::WriteBlock(unsigned qsize) {
107  if (!reader) {
108  while (WriteBlocked() && !reader) {
109  Wait();
110  }
111  }
112  if (!WriteBlocked()) { return; }
113  readtagchanged = false;
114  try {
115  while (incomm) { Wait(); }
116  ScopeSetter<bool> ss(incomm, true);
117  AutoUnlock<QueueBase> au(*this);
118  writer->Block(reader->GetPublicTag(), qsize);
119  } catch (...) { Signal(); throw; }
120  Signal();
121  while (WriteBlocked()) {
122  if (readtagchanged) {
123  readtagchanged = false;
124  bool detect;
125  try {
126  while (incomm) { Wait(); }
127  ScopeSetter<bool> ss(incomm, true);
128  AutoUnlock<QueueBase> au(*this);
129  detect = writer->Transmit(reader->GetPublicTag());
130  } catch (...) { Signal(); throw; }
131  Signal();
132  if (detect) { Detect(); }
133  } else {
134  Wait();
135  }
136  }
137  }
138 
140  AutoLock<QueueBase> al(*this);
142  }
143 
145  DEBUG("%s: (%llu -> %llu)\n", __PRETTY_FUNCTION__, (writer ? writer->GetPrivateTag().Key() : 0), (reader ? reader->GetPrivateTag().Key() : 0));
146  readtagchanged = true;
147  Signal();
148  }
149 
151  AutoLock<QueueBase> al(*this);
153  }
154 
156  DEBUG("%s: (%llu -> %llu)\n", __PRETTY_FUNCTION__, (writer ? writer->GetPrivateTag().Key() : 0), (reader ? reader->GetPrivateTag().Key() : 0));
157  writetagchanged = true;
158  Signal();
159  }
160 
161 }
162 
virtual void Detect()=0
shared_ptr< Node > reader
Definition: D4RQueue.h:122
#define DEBUG(fmt,...)
Definition: D4RQueue.cc:34
virtual bool WriteBlocked()=0
void SetReaderNode(shared_ptr< Node > n)
Definition: D4RQueue.cc:59
The exception thrown when true deadlock is detected.
~ScopeSetter()
Definition: D4RQueue.cc:44
virtual void Wait()=0
shared_ptr< Node > writer
Definition: D4RQueue.h:123
virtual bool ReadBlocked()=0
void SignalWriterTagChanged()
Definition: D4RQueue.cc:150
void WriteBlock(unsigned qsize)
Definition: D4RQueue.cc:106
void SignalReaderTagChanged()
Definition: D4RQueue.cc:139
virtual ~QueueBase()
Definition: D4RQueue.cc:57
virtual void UnlockedSignalReaderTagChanged()
Definition: D4RQueue.cc:144
virtual void UnlockedSignalWriterTagChanged()
Definition: D4RQueue.cc:155
void ReadBlock()
Definition: D4RQueue.cc:71
bool readtagchanged
Definition: D4RQueue.h:124
virtual void Signal()=0
ScopeSetter(T &val_, T set)
Definition: D4RQueue.cc:40
An exception thrown when a true deadlock is detected.
void SetWriterNode(shared_ptr< Node > n)
Definition: D4RQueue.cc:65
bool writetagchanged
Definition: D4RQueue.h:125
Automatic locking on the stack.