Skip to content

My thread pool - #22

Open
Palezehvat wants to merge 17 commits into
masterfrom
MyThreadPool
Open

Palezehvat wants to merge 17 commits into
masterfrom
MyThreadPool

Conversation

@Palezehvat

Copy link
Copy Markdown
Owner

No description provided.

Comment thread MyThreadPool/MyThreadPool/IMyTask.cs Outdated
/// <summary>
/// A method for solving subtasks from the results obtained from the tasks
/// </summary>
public IMyTask<TNewResult> ContinueWith<TNewResult>(Func<TResult, TNewResult> suppiler);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Комментарии должны присутствовать у всех public-методов, а не выборочно :)

Comment thread MyThreadPool/MyThreadPool/IMyTask.cs Outdated
/// <summary>
/// A method for solving subtasks from the results obtained from the tasks
/// </summary>
public IMyTask<TNewResult> ContinueWith<TNewResult>(Func<TResult, TNewResult> suppiler);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

supplier
Здесь и в других местах

private readonly CancellationTokenSource token = new();
private readonly Object lockerForThreads;
private readonly Object lockerForTasks;
private volatile bool stopCount = false;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Компилятор ругается, что значение поля нигде не используется

/// Accepts a function, adds it as a task in the thread, and returns the created task
/// </summary>
public IMyTask<TResult> Submit<TResult>(Func<TResult> suppiler)
{

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Здесь надо учесть условие "после вызова Shutdown новые задачи не принимаются на исполнение потоками из пула", а также согласовать исполнение метод с Shutdown (сделать так, чтобы не было гонок при вызове Submit и Shutdown одновременно из разных потоков)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Согласование Submit с Shutdown -- не готово.
(для этого надо использовать lock по защищаемому ресурсу)

Comment on lines +58 to +61
if (token.IsCancellationRequested)
{
;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это как?..

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Видимо, поле stopCount создавалось как показатель, был ли уже запрошен Shutdown. Тогда надо его либо свойством сделать, либо вообще убрать. Если свойством сделать, то у stopCount будет хоть какое-то гипотетическое применение в виде запрашивания извне.
И назвать тогда как-то понятнее, типо IsShutdownRequested

Comment thread MyThreadPool/MyThreadPool/MyTask.cs Outdated
isCompleted = true;
while (queueWithContinueWithTasks.Count > 0)
{
queueWithTasks.Enqueue(queueWithContinueWithTasks.Dequeue());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

По-хорошему, напрямую с очередью должен работать только пул и его треды. Task - это уже другой уровень абстракции, он лишь вызывает методы треда типо Submit. Поэтому здесь надо переписать через Submit треда

Comment thread MyThreadPool/MyThreadPool/MyTask.cs Outdated
private volatile bool isCompleted = false;
private TResult? result;
private readonly Queue<Action> queueWithContinueWithTasks;
private readonly MyThread[] arrayThreads;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Зачем это поле?

Comment thread MyThreadPool/MyThreadPool/MyTask.cs Outdated
}

public IMyTask<TNewResult> ContinueWith<TNewResult>(Func<TResult, TNewResult> suppiler)
{

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Здесь тоже прямую работу с очередью задач пула надо заменить на Submit. Иначе если кто-угодно будет его очередь менять, сложно будет найти ошибку. Да и не в духе ООП это

Comment thread MyThreadPool/MyThreadPool/MyTask.cs Outdated
}

public IMyTask<TNewResult> ContinueWith<TNewResult>(Func<TResult, TNewResult> suppiler)
{

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Здесь тоже надо позаботиться об отсутствии гонок между ContinueWith и Shutdown, между добавлением continuation-ов на пул и Shutdown (используя lock(и))

Assert.That(Equals(myTask.Result, "16"));
myThreadPool.Shutdown();
}
} No newline at end of file

@YuriUfimtsev YuriUfimtsev Nov 4, 2023

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тестов стоит добавить: тест, проверяющий, что в пуле действительно не менее n потоков; тест на корректность IsCompleted, Result (в случае с исключением); тест на Shutdown (проверить, что "уже запущенные задачи не прерываются, но новые задачи не принимаются на исполнение потоками из пула"); тесты на конкурентный доступ к методам пула из нескольких потоков (submit задач из разных потоков, Submit и Shutdown одновременно)

@YuriUfimtsev YuriUfimtsev left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Уже лучше, но исправлено не всё. И куда-то исчез механизм работы с continuation-ами задач

Comment on lines +135 to +138
if (token.IsCancellationRequested)
{
return;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это зачем? Само выйдет

/// Accepts a function, adds it as a task in the thread, and returns the created task
/// </summary>
public IMyTask<TResult> Submit<TResult>(Func<TResult> suppiler)
{

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Согласование Submit с Shutdown -- не готово.
(для этого надо использовать lock по защищаемому ресурсу)


if (!token.IsCancellationRequested)
{
return pool.Submit(() => supplier(Result));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ниже компилятор ругается: действительно, почему supplier может быть null?

waitHandle.WaitOne();
if (!token.IsCancellationRequested)
{
lock (locker)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Здесь lock по очереди задач надо, как ранее писал

/// <summary>
/// A method for solving subtasks from the results obtained from the tasks
/// </summary>
public IMyTask<TNewResult> ContinueWith<TNewResult>(Func<TResult, TNewResult> supplier)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Здесь и в StartSupplier куда-то пропала функциональность по добавлению всех continuation-ов в очередь и сабмиту этих continuation-ов в тредпул, когда "базовая" задача досчиталась. А это для выполнения условий задачи важно

Comment on lines +33 to +34
Assert.That(firstTask.Result, Is.EqualTo(4));
Assert.That(secondTask.Result, Is.EqualTo(6));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А вот это хорошо, никаких Assert.That(Equals(..)) 👍

private TResult? result;
private Exception? exception;
private CancellationTokenSource token;
private EventWaitHandle waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Эквивалентно

Suggested change
private EventWaitHandle waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
private ManualResetEvent resetEvent = new ManualResetEvent(false);

Удобнее использовать и более распространено :)
Для пропуска одного потока, а не всех сразу, есть AutoResetEvent

/// </summary>
public MyThreadPool(int sizeThreads)
{
waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Здесь тоже лучше ManualResetEvent использовать. Хотя если вы его используйте для пропуска одного потока для выполнения задачи при Submit, то лучше AutoResetEvent. MRE только все потоки умеет пропускать за раз


[Test]
public void NumberThreadsTheRequiredNumberIsCreated()
{

@YuriUfimtsev YuriUfimtsev Dec 21, 2023

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не, так просто не получится. Вдруг GetNumberOfThreads просто заданное число возвращает :)
Здесь надо загрузить все потоки пула задачами и проверить, что новая добавленная задача не будет принята на исполнение. Для того, чтобы загрузить потоки задачами, внутри задач можно использовать ManualResetEvent


using MyThreadPool;

public class Tests

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тестов на конкурентный доступ к методам пула по-прежнему не хватает

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants