/[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 26 by schoenebeck, Fri Dec 26 16:39:58 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, bool DoLoop) {
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        cmd.DoLoop       = DoLoop;
64    
65      CreationQueue->write(&cmd, 1);      CreationQueue->push(&cmd);
66      return 0;      return 0;
67  }  }
68    
# Line 60  int DiskThread::OrderNewStream(Stream::r Line 72  int DiskThread::OrderNewStream(Stream::r
72   */   */
73  int DiskThread::OrderDeletionOfStream(Stream::reference_t* pStreamRef) {  int DiskThread::OrderDeletionOfStream(Stream::reference_t* pStreamRef) {
74      dmsg(4,("Disk Thread: stream deletion ordered\n"));      dmsg(4,("Disk Thread: stream deletion ordered\n"));
75      if (DeletionQueue->write_space() < 1) return -1;      if (DeletionQueue->write_space() < 1) {
76            dmsg(1,("DiskThread: Deletion queue full!\n"));
77            return -1;
78        }
79    
80      delete_command_t cmd;      delete_command_t cmd;
81      cmd.pStream = pStreamRef->pStream;      cmd.pStream = pStreamRef->pStream;
82      cmd.hStream = pStreamRef->hStream;      cmd.hStream = pStreamRef->hStream;
83      cmd.OrderID = pStreamRef->OrderID;      cmd.OrderID = pStreamRef->OrderID;
84    
85      DeletionQueue->write(&cmd, 1);      DeletionQueue->push(&cmd);
86      return 0;      return 0;
87  }  }
88    
# Line 87  int DiskThread::OrderDeletionOfStream(St Line 102  int DiskThread::OrderDeletionOfStream(St
102  Stream* DiskThread::AskForCreatedStream(Stream::OrderID_t StreamOrderID) {  Stream* DiskThread::AskForCreatedStream(Stream::OrderID_t StreamOrderID) {
103      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));
104      Stream* pStream = pCreatedStreams[StreamOrderID];      Stream* pStream = pCreatedStreams[StreamOrderID];
105      if (pStream) { dmsg(4,("(yes created)")) }      if (pStream && pStream != SLOT_RESERVED) {
106      else         { dmsg(4,("(no not yet created)")) }          dmsg(4,("(yes created)\n"));
107      pCreatedStreams[StreamOrderID] = NULL; // free the slot for a new order          pCreatedStreams[StreamOrderID] = NULL; // free the slot for a new order
108        }
109        else dmsg(4,("(no not yet created)\n"));
110      return pStream;      return pStream;
111  }  }
112    
# Line 103  Stream* DiskThread::AskForCreatedStream( Line 120  Stream* DiskThread::AskForCreatedStream(
120  DiskThread::DiskThread(uint BufferWrapElements) : Thread(false, 1, -2) {  DiskThread::DiskThread(uint BufferWrapElements) : Thread(false, 1, -2) {
121      CreationQueue       = new RingBuffer<create_command_t>(1024);      CreationQueue       = new RingBuffer<create_command_t>(1024);
122      DeletionQueue       = new RingBuffer<delete_command_t>(1024);      DeletionQueue       = new RingBuffer<delete_command_t>(1024);
123        GhostQueue          = new RingBuffer<Stream::Handle>(MAX_INPUT_STREAMS);
124      Streams             = MAX_INPUT_STREAMS;      Streams             = MAX_INPUT_STREAMS;
125      RefillStreamsPerRun = 4;      RefillStreamsPerRun = REFILL_STREAMS_PER_RUN;
126      for (int i = 0; i < MAX_INPUT_STREAMS; i++) {      for (int i = 0; i < MAX_INPUT_STREAMS; i++) {
127          pStreams[i] = new Stream(131072, BufferWrapElements); // 131072 sample words          pStreams[i] = new Stream(STREAM_BUFFER_SIZE, BufferWrapElements); // 131072 sample words
128      }      }
129      for (int i = 1; i <= MAX_INPUT_STREAMS; i++) {      for (int i = 1; i <= MAX_INPUT_STREAMS; i++) {
130          pCreatedStreams[i] = NULL;          pCreatedStreams[i] = NULL;
# Line 119  DiskThread::~DiskThread() { Line 137  DiskThread::~DiskThread() {
137      }      }
138      if (CreationQueue) delete CreationQueue;      if (CreationQueue) delete CreationQueue;
139      if (DeletionQueue) delete DeletionQueue;      if (DeletionQueue) delete DeletionQueue;
140        if (GhostQueue)    delete GhostQueue;
141  }  }
142    
143  int DiskThread::Main() {  int DiskThread::Main() {
# Line 126  int DiskThread::Main() { Line 145  int DiskThread::Main() {
145      while (true) {      while (true) {
146          IsIdle = true; // will be set to false if a stream got filled          IsIdle = true; // will be set to false if a stream got filled
147    
148            // if there are ghost streams, delete them
149            for (int i = 0; i < GhostQueue->read_space(); i++) { //FIXME: unefficient
150                Stream::Handle hGhostStream;
151                GhostQueue->pop(&hGhostStream);
152                bool found = false;
153                for (int i = 0; i < this->Streams; i++) {
154                    if (pStreams[i]->GetHandle() == hGhostStream) {
155                        pStreams[i]->Kill();
156                        found = true;
157                        break;
158                    }
159                }
160                if (!found) GhostQueue->push(&hGhostStream); // put ghost stream handle back to the queue
161            }
162    
163          // if there are creation commands, create new streams          // if there are creation commands, create new streams
164          while (Stream::UnusedStreams > 0 && CreationQueue->read_space() > 0) {          while (Stream::UnusedStreams > 0 && CreationQueue->read_space() > 0) {
165              create_command_t command;              create_command_t command;
166              CreationQueue->read(&command, 1);              CreationQueue->pop(&command);
167              CreateStream(command);              CreateStream(command);
168          }          }
169    
170          // if there are deletion commands, delete those streams          // if there are deletion commands, delete those streams
171          while (Stream::UnusedStreams < Streams && DeletionQueue->read_space() > 0) {          while (Stream::UnusedStreams < Streams && DeletionQueue->read_space() > 0) {
172              delete_command_t command;              delete_command_t command;
173              DeletionQueue->read(&command, 1);              DeletionQueue->pop(&command);
174              DeleteStream(command);              DeleteStream(command);
175          }          }
176    
# Line 167  void DiskThread::CreateStream(create_com Line 201  void DiskThread::CreateStream(create_com
201          }          }
202      }      }
203      if (!newstream) {      if (!newstream) {
204          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;
205          return;          return;
206      }      }
207      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, Command.DoLoop);
208      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));
209      pCreatedStreams[Command.pStreamRef->OrderID] = newstream;      if (pCreatedStreams[Command.OrderID] != SLOT_RESERVED) {
210            std::cerr << "DiskThread: Slot " << Command.OrderID << " already occupied! Please report this!\n" << std::flush;
211            newstream->Kill();
212            return;
213        }
214        pCreatedStreams[Command.OrderID] = newstream;
215  }  }
216    
217  void DiskThread::DeleteStream(delete_command_t& Command) {  void DiskThread::DeleteStream(delete_command_t& Command) {
218      if (Command.pStream) Command.pStream->Kill();      if (Command.pStream) Command.pStream->Kill();
219      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
220    
221          // stream was created but not picked up yet          // if stream was created but not picked up yet
222          Stream* pStream = pCreatedStreams[Command.OrderID];          Stream* pStream = pCreatedStreams[Command.OrderID];
223          if (pStream) {          if (pStream && pStream != SLOT_RESERVED) {
224              pStream->Kill();              pStream->Kill();
225              pCreatedStreams[Command.OrderID] = NULL; // free slot for new order              pCreatedStreams[Command.OrderID] = NULL; // free slot for new order
226              return;              return;
227          }          }
228    
229          // else we have to compare the handle with the one's of all streams          // the stream was not created yet
230          // (this case should occur only very rarely)          if (GhostQueue->write_space() > 0) {
231          for (int i = 0; i < this->Streams; i++) {              GhostQueue->push(&Command.hStream);
             if (pStreams[i]->GetHandle() == Command.hStream) {  
                 pStreams[i]->Kill();  
                 return;  
             }  
232          }          }
233            else dmsg(1,("DiskThread: GhostQueue full!\n"));
234      }      }
235  }  }
236    
# Line 237  Stream::Handle DiskThread::CreateHandle( Line 273  Stream::Handle DiskThread::CreateHandle(
273  /// order ID Generator  /// order ID Generator
274  Stream::OrderID_t DiskThread::CreateOrderID() {  Stream::OrderID_t DiskThread::CreateOrderID() {
275      static uint32_t counter = 0;      static uint32_t counter = 0;
276      do {      for (int i = 0; i < MAX_INPUT_STREAMS; i++) {
277          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
278          else                              counter++;          else                              counter++;
279      } while (pCreatedStreams[counter]); // until empty slot found          if (!pCreatedStreams[counter]) {
280      return counter;              pCreatedStreams[counter] = SLOT_RESERVED; // mark this slot as reserved
281                return counter;                           // found empty slot
282            }
283        }
284        return 0; // no free slot
285  }  }
286    
287    

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

  ViewVC Help
Powered by ViewVC