示例#1
0
        /// <summary>
        /// Kick start of a zip/unzip process
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="readerThread"></param>
        /// <param name="workers"></param>
        /// <param name="buffers"></param>
        static void StartConveyor(ArchReader reader, ThreadWorker readerThread, ThreadWorker[] workers, InOutBuffer[] buffers)
        {
            Debug.Assert(workers.Length == buffers.Length);

            for (int idx = 0; idx < workers.Length; idx++)
            {
                ThreadWorker worker = workers[idx];

                General.Log($"{idx} start reading");
                reader.Buffer = buffers[idx];
                readerThread.haveWork.Set();

                readerThread.notifyDone.WaitOne();
                General.Log($"{idx} reading chunk complete, start zippin");
                worker.haveWork.Set();
                worker.Start();
            }
        }
        /// <summary>
        /// Kick start of a zip/unzip process
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="workers"></param>
        /// <param name="workersTasks"></param>
        /// <param name="buffers"></param>
        async static Task StartConveyor(ArchReader reader, ArchWorker[] workers, Task[] workerTasks, InOutBuffer[] buffers)
        {
            Debug.Assert(workers.Length == buffers.Length);

            for (int idx = 0; idx < workers.Length; idx++)
            {
                ArchWorker worker = workers[idx];

                General.Log($"{idx} start reading");
                reader.Buffer = buffers[idx];
                //readerThread.haveWork.Set();
                //readerThread.notifyDone.WaitOne();
                await reader.ReadAsync();

                General.Log($"{idx} reading chunk complete, start zippin");

                workerTasks[idx] = worker.DoWorkAsync();
            }
        }
        async private static Task ManageThreadsAsync(string inputName, string outputName, ArchAction act, int bufferSize, uint workersCount = 0)
        {
            InOutBuffer[] buffers     = null;
            Task[]        workerTasks = null;

            try
            {
                General.Log($"Started '{inputName}' {act} into '{outputName}'...");

                if (bufferSize < defaultChunkSize)
                {
                    bufferSize = defaultChunkSize;
                }

                if (workersCount < 1)
                {
                    workersCount = ChooseWorkersCount();
                }

                General.Log($"buffer size {bufferSize}, workers count {workersCount}");

                //to feel good let's use 'using'

                // objects for input reading
                using FileStream inFileStream = File.OpenRead(inputName);
                ArchReader reader = new ArchReader(inFileStream, act);

                // objects for output writing
                using FileStream outFileStream = File.Create(outputName);
                ArchWriter writer = new ArchWriter(outFileStream, act);

                // create objects to do zipping/unzipping
                CreateBuffersAndWorkers(act, bufferSize, workersCount, out buffers, out ArchWorker[] workers, out workerTasks);

                await StartConveyor(reader, workers, workerTasks, buffers);

                int idx = 0;

                // as long as there are bytes read from input, keep conveyor
                // when no more input data, set this flag & wait till all therads are finihed.
                bool finishing = false;

                do
                {
                    ArchWorker worker = workers[idx];

                    if (worker == null)
                    {
                        General.Log($"all workers are finished");
                        break;
                    }

                    General.Log($"Wait for worker {idx} done, to start writting");
                    await workerTasks[idx];//wait till zipper idx has done

                    General.Log($"{idx} start writting");

                    writer.Buffer = buffers[idx];
                    Task writerTask = writer.WriteAsync();

                    if (!finishing)
                    {
                        General.Log($"{idx} start reading next portion");
                        reader.Buffer = buffers[idx];
                        Task readerTask = reader.ReadAsync();

                        General.Log($"{idx} need both In & Out buffers to be Ready to start next part zip/unzip");
                        await readerTask;

                        // check if have read anyting
                        if (reader.Buffer.BytesRead <= 0)
                        {
                            //have read all, and all is (being) processed
                            finishing = true;
                        }
                    }

                    await writerTask;

                    if (finishing)
                    {
                        workers[idx]     = null;
                        workerTasks[idx] = null; //according to info from ms , no need to dispose a Task
                        buffers[idx]     = null;
                    }
                    else
                    {
                        workerTasks[idx] = worker.DoWorkAsync();
                    }

                    //cause rotating, and output shall be in-order
                    if (++idx >= workers.Length)
                    {
                        idx = 0;
                    }
                } while (true);

                General.Log($"{act} finished successfuly.");
            }
            catch (Exception exc)
            {
                General.Log($"ManageThreads encountered an error {exc.Message} returning to caller.");
                throw;
            }
            finally
            {
                CleanUp(buffers, workerTasks);
            }
        }
示例#4
0
        private static void ManageThreads(string inputName, string outputName, ArchAction act, int bufferSize, uint workersCount = 0)
        {
            InOutBuffer[]  buffers = null;
            ThreadWorker[] workers = null;

            try
            {
                General.Log($"Started '{inputName}' {act} into '{outputName}'...");

                if (bufferSize < defaultChunkSize)
                {
                    bufferSize = defaultChunkSize;
                }

                if (workersCount < 1)
                {
                    workersCount = ChooseWorkersCount();
                }

                General.Log($"buffer size {bufferSize}, workers count {workersCount}");

                //to feel good let's use 'using'

                // objects for input reading
                using FileStream inFileStream = File.OpenRead(inputName);
                ArchReader reader = new ArchReader(inFileStream, act);
                using ThreadWorker readerThread = new ThreadWorker(reader, true);

                // objects for output writing
                using FileStream outFileStream = File.Create(outputName);
                ArchWriter writer = new ArchWriter(outFileStream, act);
                using ThreadWorker writerThread = new ThreadWorker(writer, true);

                // create objects to do zipping/unzipping
                CreateBuffersAndWorkers(act, bufferSize, workersCount, out buffers, out workers);

                StartConveyor(reader, readerThread, workers, buffers);

                int idx = 0;

                // as long as there are bytes read from input, keep conveyor
                // when no more input data, set this flag & wait till all therads are finihed.
                bool finishing = false;

                do
                {
                    ThreadWorker worker = workers[idx];

                    if (worker == null)
                    {
                        General.Log($"all threads are finished");
                        // good place to let the writer go
                        writerThread.Finish();
                        //writerThread.Dispose();
                        break;
                    }

                    General.Log($"main thread about to Wait for worker {idx} done, to start writting");
                    worker.notifyDone.WaitOne(); //wait till zipper idx has done

                    General.Log($"{idx} start writting");

                    writer.Buffer = buffers[idx];
                    writerThread.haveWork.Set();

                    if (!finishing)
                    {
                        General.Log($"{idx} start reading next portion");
                        reader.Buffer = buffers[idx];
                        readerThread.haveWork.Set();

                        General.Log($"{idx} need both In & Out buffers to be Ready to start next part zippin");
                        readerThread.notifyDone.WaitOne();

                        // check if have read anyting
                        if (reader.Buffer.BytesRead <= 0)
                        {
                            //have read all, and all is (being) processed
                            finishing = true;

                            // right place to set the reader free
                            readerThread.Finish();
                            //readerThread.Dispose();
                        }
                    }

                    writerThread.notifyDone.WaitOne();

                    if (finishing)
                    {
                        worker.Finish();
                        workers[idx].Dispose();
                        workers[idx] = null;
                        //can clean buffers here as well
                        buffers[idx].Dispose();
                        buffers[idx] = null;
                    }
                    else
                    {
                        worker.haveWork.Set();
                    }

                    //cause rotating, and output shall be in-order
                    if (++idx >= workers.Length)
                    {
                        idx = 0;
                    }
                } while (true);

                General.Log($"{act} finished successfuly.");
            }
            catch (Exception exc)
            {
                General.Log($"ManageThreads encountered an error {exc.Message} returning to caller.");
                throw;
            }
            finally
            {
                CleanUp(buffers, workers);
            }
        }