/[svn]/linuxsampler/trunk/src/diskthread.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/diskthread.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 13 by schoenebeck, Fri Nov 21 15:07:23 2003 UTC revision 18 by schoenebeck, Sun Dec 7 05:03:43 2003 UTC
# Line 27  Line 27 
27  // *  // *
28    
29    
30    // just a placeholder to mark a cell in the pickup array as 'reserved'
31    Stream* DiskThread::SLOT_RESERVED = (Stream*) &SLOT_RESERVED;
32    
33    
34  // #########################################################################  // #########################################################################
35  // # Foreign Thread Section  // # Foreign Thread Section
36  // #         (following code intended to be interface for audio thread)  // #         (following code intended to be interface for audio thread)
37    
38    
39  /**  /**
40   * Returns -1 if command queue is full, 0 on success (will be called by audio   * Returns -1 if command queue or pickup pool is full, 0 on success (will be
41   * thread within the voice class).   * called by audio thread within the voice class).
42   */   */
43  int DiskThread::OrderNewStream(Stream::reference_t* pStreamRef, gig::Sample* pSample, unsigned long SampleOffset) {  int DiskThread::OrderNewStream(Stream::reference_t* pStreamRef, gig::Sample* pSample, unsigned long SampleOffset) {
44      dmsg(4,("Disk Thread: new stream ordered\n"));      dmsg(4,("Disk Thread: new stream ordered\n"));
45      if (CreationQueue->write_space() < 1) return -1;      if (CreationQueue->write_space() < 1) {
46            dmsg(1,("DiskThread: Order queue full!\n"));
47            return -1;
48        }
49    
50      pStreamRef->State   = Stream::state_active;      pStreamRef->State   = Stream::state_active;
51      pStreamRef->OrderID = CreateOrderID();      pStreamRef->OrderID = CreateOrderID();
52      pStreamRef->hStream = CreateHandle();      pStreamRef->hStream = CreateHandle();
53      pStreamRef->pStream = NULL; // a stream has to be activated by the disk thread first      pStreamRef->pStream = NULL; // a stream has to be activated by the disk thread first
54    
55        if (!pStreamRef->OrderID) return -1; // there was no free slot
56    
57      create_command_t cmd;      create_command_t cmd;
58        cmd.OrderID      = pStreamRef->OrderID;
59        cmd.hStream      = pStreamRef->hStream;
60      cmd.pStreamRef   = pStreamRef;      cmd.pStreamRef   = pStreamRef;
61      cmd.pSample      = pSample;      cmd.pSample      = pSample;
62      cmd.SampleOffset = SampleOffset;      cmd.SampleOffset = SampleOffset;
63    
64      CreationQueue->write(&cmd, 1);      CreationQueue->push(&cmd);
65      return 0;      return 0;
66  }  }
67    
# Line 60  int DiskThread::OrderNewStream(Stream::r Line 71  int DiskThread::OrderNewStream(Stream::r
71   */   */
72  int DiskThread::OrderDeletionOfStream(Stream::reference_t* pStreamRef) {  int DiskThread::OrderDeletionOfStream(Stream::reference_t* pStreamRef) {
73      dmsg(4,("Disk Thread: stream deletion ordered\n"));      dmsg(4,("Disk Thread: stream deletion ordered\n"));
74      if (DeletionQueue->write_space() < 1) return -1;      if (DeletionQueue->write_space() < 1) {
75            dmsg(1,("DiskThread: Deletion queue full!\n"));
76            return -1;
77        }
78    
79      delete_command_t cmd;      delete_command_t cmd;
80      cmd.pStream = pStreamRef->pStream;      cmd.pStream = pStreamRef->pStream;
81      cmd.hStream = pStreamRef->hStream;      cmd.hStream = pStreamRef->hStream;
82      cmd.OrderID = pStreamRef->OrderID;      cmd.OrderID = pStreamRef->OrderID;
83    
84      DeletionQueue->write(&cmd, 1);      DeletionQueue->push(&cmd);
85      return 0;      return 0;
86  }  }
87    
# Line 87  int DiskThread::OrderDeletionOfStream(St Line 101  int DiskThread::OrderDeletionOfStream(St
101  Stream* DiskThread::AskForCreatedStream(Stream::OrderID_t StreamOrderID) {  Stream* DiskThread::AskForCreatedStream(Stream::OrderID_t StreamOrderID) {
102      dmsg(4,("Disk Thread: been asked if stream already created, OrderID=%x ", StreamOrderID));      dmsg(4,("Disk Thread: been asked if stream already created, OrderID=%x ", StreamOrderID));
103      Stream* pStream = pCreatedStreams[StreamOrderID];      Stream* pStream = pCreatedStreams[StreamOrderID];
104      if (pStream) { dmsg(4,("(yes created)")) }      if (pStream && pStream != SLOT_RESERVED) {
105      else         { dmsg(4,("(no not yet created)")) }          dmsg(4,("(yes created)\n"));
106      pCreatedStreams[StreamOrderID] = NULL; // free the slot for a new order          pCreatedStreams[StreamOrderID] = NULL; // free the slot for a new order
107        }
108        else dmsg(4,("(no not yet created)\n"));
109      return pStream;      return pStream;
110  }  }
111    
# Line 103  Stream* DiskThread::AskForCreatedStream( Line 119  Stream* DiskThread::AskForCreatedStream(
119  DiskThread::DiskThread(uint BufferWrapElements) : Thread(false, 1, -2) {  DiskThread::DiskThread(uint BufferWrapElements) : Thread(false, 1, -2) {
120      CreationQueue       = new RingBuffer<create_command_t>(1024);      CreationQueue       = new RingBuffer<create_command_t>(1024);
121      DeletionQueue       = new RingBuffer<delete_command_t>(1024);      DeletionQueue       = new RingBuffer<delete_command_t>(1024);
122        GhostQueue          = new RingBuffer<Stream::Handle>(MAX_INPUT_STREAMS);
123      Streams             = MAX_INPUT_STREAMS;      Streams             = MAX_INPUT_STREAMS;
124      RefillStreamsPerRun = 4;      RefillStreamsPerRun = REFILL_STREAMS_PER_RUN;
125      for (int i = 0; i < MAX_INPUT_STREAMS; i++) {      for (int i = 0; i < MAX_INPUT_STREAMS; i++) {
126          pStreams[i] = new Stream(131072, BufferWrapElements); // 131072 sample words          pStreams[i] = new Stream(STREAM_BUFFER_SIZE, BufferWrapElements); // 131072 sample words
127      }      }
128      for (int i = 1; i <= MAX_INPUT_STREAMS; i++) {      for (int i = 1; i <= MAX_INPUT_STREAMS; i++) {
129          pCreatedStreams[i] = NULL;          pCreatedStreams[i] = NULL;
# Line 119  DiskThread::~DiskThread() { Line 136  DiskThread::~DiskThread() {
136      }      }
137      if (CreationQueue) delete CreationQueue;      if (CreationQueue) delete CreationQueue;
138      if (DeletionQueue) delete DeletionQueue;      if (DeletionQueue) delete DeletionQueue;
139        if (GhostQueue)    delete GhostQueue;
140  }  }
141    
142  int DiskThread::Main() {  int DiskThread::Main() {
# Line 126  int DiskThread::Main() { Line 144  int DiskThread::Main() {
144      while (true) {      while (true) {
145          IsIdle = true; // will be set to false if a stream got filled          IsIdle = true; // will be set to false if a stream got filled
146    
147            // if there are ghost streams, delete them
148            for (int i = 0; i < GhostQueue->read_space(); i++) { //FIXME: unefficient
149                Stream::Handle hGhostStream;
150                GhostQueue->pop(&hGhostStream);
151                bool found = false;
152                for (int i = 0; i < this->Streams; i++) {
153                    if (pStreams[i]->GetHandle() == hGhostStream) {
154                        pStreams[i]->Kill();
155                        found = true;
156                        break;
157                    }
158                }
159                if (!found) GhostQueue->push(&hGhostStream); // put ghost stream handle back to the queue
160            }
161    
162          // if there are creation commands, create new streams          // if there are creation commands, create new streams
163          while (Stream::UnusedStreams > 0 && CreationQueue->read_space() > 0) {          while (Stream::UnusedStreams > 0 && CreationQueue->read_space() > 0) {
164              create_command_t command;              create_command_t command;
165              CreationQueue->read(&command, 1);              CreationQueue->pop(&command);
166              CreateStream(command);              CreateStream(command);
167          }          }
168    
169          // if there are deletion commands, delete those streams          // if there are deletion commands, delete those streams
170          while (Stream::UnusedStreams < Streams && DeletionQueue->read_space() > 0) {          while (Stream::UnusedStreams < Streams && DeletionQueue->read_space() > 0) {
171              delete_command_t command;              delete_command_t command;
172              DeletionQueue->read(&command, 1);              DeletionQueue->pop(&command);
173              DeleteStream(command);              DeleteStream(command);
174          }          }
175    
# Line 167  void DiskThread::CreateStream(create_com Line 200  void DiskThread::CreateStream(create_com
200          }          }
201      }      }
202      if (!newstream) {      if (!newstream) {
203          dmsg(1,("No unused stream found (OrderID:%x) - report if this happens, this is a bug!\n", Command.pStreamRef->OrderID));          std::cerr << "No unused stream found (OrderID:" << Command.OrderID << ") - report if this happens, this is a bug!\n" << std::flush;
204          return;          return;
205      }      }
206      dmsg(4,("new Stream launched by disk thread (OrderID:%x,StreamHandle:%x)\n", Command.pStreamRef->OrderID, Command.pStreamRef->hStream));      newstream->Launch(Command.hStream, Command.pStreamRef, Command.pSample, Command.SampleOffset);
207      newstream->Launch(Command.pStreamRef, Command.pSample, Command.SampleOffset);      dmsg(4,("new Stream launched by disk thread (OrderID:%d,StreamHandle:%d)\n", Command.OrderID, Command.hStream));
208      pCreatedStreams[Command.pStreamRef->OrderID] = newstream;      if (pCreatedStreams[Command.OrderID] != SLOT_RESERVED) {
209            std::cerr << "DiskThread: Slot " << Command.OrderID << " already occupied! Please report this!\n" << std::flush;
210            newstream->Kill();
211            return;
212        }
213        pCreatedStreams[Command.OrderID] = newstream;
214  }  }
215    
216  void DiskThread::DeleteStream(delete_command_t& Command) {  void DiskThread::DeleteStream(delete_command_t& Command) {
217      if (Command.pStream) Command.pStream->Kill();      if (Command.pStream) Command.pStream->Kill();
218      else { // the stream wasn't created by disk thread or picked up by audio thread yet      else { // the stream wasn't created by disk thread or picked up by audio thread yet
219    
220          // stream was created but not picked up yet          // if stream was created but not picked up yet
221          Stream* pStream = pCreatedStreams[Command.OrderID];          Stream* pStream = pCreatedStreams[Command.OrderID];
222          if (pStream) {          if (pStream && pStream != SLOT_RESERVED) {
223              pStream->Kill();              pStream->Kill();
224              pCreatedStreams[Command.OrderID] = NULL; // free slot for new order              pCreatedStreams[Command.OrderID] = NULL; // free slot for new order
225              return;              return;
226          }          }
227    
228          // else we have to compare the handle with the one's of all streams          // the stream was not created yet
229          // (this case should occur only very rarely)          if (GhostQueue->write_space() > 0) {
230          for (int i = 0; i < this->Streams; i++) {              GhostQueue->push(&Command.hStream);
             if (pStreams[i]->GetHandle() == Command.hStream) {  
                 pStreams[i]->Kill();  
                 return;  
             }  
231          }          }
232            else dmsg(1,("DiskThread: GhostQueue full!\n"));
233      }      }
234  }  }
235    
# Line 237  Stream::Handle DiskThread::CreateHandle( Line 272  Stream::Handle DiskThread::CreateHandle(
272  /// order ID Generator  /// order ID Generator
273  Stream::OrderID_t DiskThread::CreateOrderID() {  Stream::OrderID_t DiskThread::CreateOrderID() {
274      static uint32_t counter = 0;      static uint32_t counter = 0;
275      do {      for (int i = 0; i < MAX_INPUT_STREAMS; i++) {
276          if (counter == MAX_INPUT_STREAMS) counter = 1; // we use '0' as 'invalid order' only, so we skip 0          if (counter == MAX_INPUT_STREAMS) counter = 1; // we use '0' as 'invalid order' only, so we skip 0
277          else                              counter++;          else                              counter++;
278      } while (pCreatedStreams[counter]); // until empty slot found          if (!pCreatedStreams[counter]) {
279      return counter;              pCreatedStreams[counter] = SLOT_RESERVED; // mark this slot as reserved
280                return counter;                           // found empty slot
281            }
282        }
283        return 0; // no free slot
284  }  }
285    
286    

Legend:
Removed from v.13  
changed lines
  Added in v.18

  ViewVC Help
Powered by ViewVC