MultythreadWay - магистраль

Обсуждение проектов наших жителей.
Вы можете выставить проект на тест или найти помощников для его реализации.

Модератор: BV

ANDLL
Великий гастроном
Великий гастроном
Аватара пользователя
 
Сообщения: 3450
Зарегистрирован: 29.06.2003 (Вс) 18:55

MultythreadWay - магистраль

Сообщение ANDLL » 13.10.2006 (Пт) 15:11

Это некоторый объект синхронизации.
Давайте представим себе некоторую магистраль(дорогу) от точки A до точки B по которой все время ездят разные автомобили. У магистрали только две точки - вход и выход, ответвлений нет. Кроме того она однополосная. Если бы она была двухполосной, мы могли бы просто представить бы ее как две независимыемые магистрали и считали бы каждую из них отдельной.
Итак, каждая машина может заезжать на магистраль[Enter] спустя некоторое время покидать ее[Leave]. Кроме того магистраль может быть ограниченной по колочиству машин, которое она в себе содержит(MaximumEntries).
Кроме магистрали есть еще и ремонтники. Они могут блокировать магистраль(Lock) и разблокировать ее(Unlock).
Блокировка магистрали заключается в том что
а) сначала закрывается вход
б) ожидается пока все машины "съедут" с магистрали.
И только после этого магистраль закрывается. При этом машины, которые хотят попасть на магистраль ждут некоторое время, пока она закончится ремонт и магситраль откроется. У этого ожидания есть два вариант:
а) Дорогу отремантирует и магистраль откроется, тогда машина заедет на магситраль(попытка входа будет успешной)
либо
б) Таймаут ожидания истечет до того как магистраль отремонтируют и тогда машина развернется обратно(и попытка входа провалится).

Где такое может понадобится? Ну положим естьь база со сложно зависимыми объектами, при чем эта база в основном читается пользователями. И положим нельзя допустить что бы то время, как какойто пользователь юзает базу для чтения, ктото ее изменил. В таком случае, пользователи "читающие" базу будут "машинами", а те службы, которые будуит ее периодически изменять - "ремотниками".

Или скажем некоторый объект, который асинхронным образом юзают разные потоки, и для которого есть еще и другие, "технические" потоки, которые периодически осуществляют запись на диск. Очевидно, что в этом случае для записи информации надо дождаться пока все рабочие потоки не закончат свою текущую работу с объектом, то есть пока они не "освободят" магистраль для проведления ремонтных работ.

О реализации. Делалась в торопях, и особо не тестировалась. Кроме того, возможно есть иные пути для реализации такой вот дороги. Буду рад услышать любую критику по этому поводу. Учитывая, что в этом деле я полный нуб, возможно так же существование некоторого стандартного объекта синхронизации. Если такой имеется, скажите мне об этом.

Код: Выделить всё
' Date: 13 october 2006
' Author: ANDLL, Web: http://danasoft.ru
' Class DANAsoft.General.Synchronization.MultythreadWay
Namespace DANAsoft.General.Synchronization
    Public Class MultythreadWay
        Public Const TIMEOUT_DEFAULT As Long = 1000
        Public MaximumEntries As Integer = -1

        Dim mThreads As New Collections.Generic.List(Of Threading.Thread)
        Dim mSyncLock As New Object

        Public Function EnterWay(Optional ByVal uTimeOut As Long = TIMEOUT_DEFAULT) As Boolean
            If Threading.Monitor.TryEnter(mSyncLock, uTimeOut) Then
                Try
                    SyncLock mThreads
                        If mThreads.Count > MaximumEntries And MaximumEntries <> -1 Then
                            Throw New InvalidOperationException("The way is overflowed now")
                        Else
                            mThreads.Add(Threading.Thread.CurrentThread)
                        End If
                    End SyncLock
                Finally
                    Threading.Monitor.Exit(mSyncLock)
                End Try
                Return True
            Else
                Return False
            End If
        End Function
        Public Sub LeaveWay()
            SyncLock mThreads
                mThreads.Remove(Threading.Thread.CurrentThread)
            End SyncLock
        End Sub

        Public Sub LockWay()
            SyncLock mThreads
                If mThreads.Contains(Threading.Thread.CurrentThread) Then
                    Throw New Exception("Thread, that entered way, can not lock it.")
                End If
                Threading.Monitor.Enter(mSyncLock)
            End SyncLock
            Do
                SyncLock mThreads
                    If mThreads.Count = 0 Then Exit Do
                    Dim I As Threading.Thread
                    For Each I In mThreads
                        If Not I.IsAlive Then
                            mThreads.Remove(I)
                            Exit For
                        End If
                    Next
                End SyncLock
                Threading.Thread.Sleep(4)
            Loop
        End Sub
        Public Sub UnlockWay()
            Threading.Monitor.Exit(mSyncLock)
        End Sub
    End Class
End Namespace
Гастрономия - наука о пище, о ее приготовлении, употреблении, переварении и испражнении.
Блог

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 13.10.2006 (Пт) 15:29

Такое бы, да под VB6, да надежное и без глюков -- очень полезная вещь была бы.
Lasciate ogni speranza, voi ch'entrate.

ANDLL
Великий гастроном
Великий гастроном
Аватара пользователя
 
Сообщения: 3450
Зарегистрирован: 29.06.2003 (Вс) 18:55

Сообщение ANDLL » 13.10.2006 (Пт) 15:31

alibek
Если дейстительно нужно будет и на VB6
Идея та же.
Но пока просьба потестить алгоритм :)
Гастрономия - наука о пище, о ее приготовлении, употреблении, переварении и испражнении.
Блог

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 13.10.2006 (Пт) 17:38

Тщательно разглядывая код, увидел подобие дедлока.
Код: Выделить всё
Машина:    If Threading.Monitor.TryEnter(mSyncLock, uTimeOut) Then  (въехала)
Ремонтник: SyncLock mThreads                                        (успешно)
           Threading.Monitor.Enter(mSyncLock)      (ждёт освобождения дороги)
Машина:    SyncLock mThreads                               (готово, приехали)
Изображение

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 14.10.2006 (Сб) 5:14

Ещё я бы ожидание выхода в LockWay сделал не через опрос каждые 4 мс, а через евент, который устанавливается машинами при выходе...
Ну что, реализовывать свой вариант?
Изображение

ANDLL
Великий гастроном
Великий гастроном
Аватара пользователя
 
Сообщения: 3450
Зарегистрирован: 29.06.2003 (Вс) 18:55

Сообщение ANDLL » 14.10.2006 (Сб) 9:29

Конечно
Гастрономия - наука о пище, о ее приготовлении, употреблении, переварении и испражнении.
Блог

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 14.10.2006 (Сб) 19:41

По идеи, по определению Кирпича, это должен быть код, который вставляется в проект и сразу же готов к юзанию.

Данный код для юзания надо ещё и корректировать, ибо это на мой взгляд пример а не Кирпич.

Рекомендую довести до ума.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Amed
Алфизик
Алфизик
 
Сообщения: 5346
Зарегистрирован: 09.03.2003 (Вс) 9:26

Сообщение Amed » 14.10.2006 (Сб) 20:37

И добавление от Amed'а: MultithreadWay, конечно же :)

ANDLL
Великий гастроном
Великий гастроном
Аватара пользователя
 
Сообщения: 3450
Зарегистрирован: 29.06.2003 (Вс) 18:55

Сообщение ANDLL » 14.10.2006 (Сб) 20:52

Amed
Так же как и с Blu-Ray это просто оригинальное название ;)
Гастрономия - наука о пище, о ее приготовлении, употреблении, переварении и испражнении.
Блог

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 14.10.2006 (Сб) 21:10

За недоработки и в связи с предложением Хакера перенесено.
Изображение

Oxygen
Белая и пушистая
Белая и пушистая
Аватара пользователя
 
Сообщения: 1314
Зарегистрирован: 15.07.2003 (Вт) 7:14
Откуда: Москва

Сообщение Oxygen » 15.10.2006 (Вс) 9:40

Насчет применения. В MSSQL для такой цели есть специальная комманда. Не помню как она выглядит, думаю, тем кому нужно будет, найти особого труда не составит. Но это уже реализованно.

А так, если в остальном, то идея интересная. Её стоит доделать, и в кирпичи. :)
Процедура клонирования завершена.
Коррекция имплантированного сознания соответствует принятым алгоритмам.
Уникальный идентификатор скопирован в чип временного паспорта.
Активация прав гражданина ожидается в течение 24 часов

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 19.10.2006 (Чт) 9:50

Код: Выделить всё
Imports System.Threading

' Эта реализация мне кажется компактнее, яснее, проще и безбажнее
' Я её, правда, ещё не тестил (мне всё равно не на чём тестить), но вроде должна работать.
Public Class MultythreadWay
    Public ReadOnly MaximumEntries As Integer = Integer.MaxValue 'больше всё равно не может быть
    Private mCount As Integer 'число вошедших нитей, вместо коллекции (теперь работает и в VS2003)
    <ThreadStatic()> Private mEntered As Boolean
    Private OneGone As New ManualResetEvent(False)

    Public Sub New()
    End Sub ' изменение MaximumEntries у живого объекта обязательно всё нарушит.
    Public Sub New(ByVal MaximumEntries As Integer)
        Me.MaximumEntries = MaximumEntries
    End Sub

    Public Function EnterWay(Optional ByVal uTimeOut As Integer = Timeout.Infinite) As Boolean
        If mEntered Then Return True
        If Not Monitor.TryEnter(Me, uTimeOut) Then Return False
        If Interlocked.Increment(mCount) < MaximumEntries Then Monitor.Exit(Me)
        ' если мы зашли последними, то не освобождаем монитор, пока нельзя войти следующему;
        ' исключение в этом случае не бросаем -- ведём себя как обычный семафор.
        mEntered = True
        Return True
    End Function
    Public Sub LeaveWay()
        If Not mEntered Then Throw New SynchronizationLockException("ещё не зашли, а уже выходим!")
        If Interlocked.Decrement(mCount) = MaximumEntries - 1 Then Monitor.Exit(Me)
        mEntered = False
        OneGone.Set()
    End Sub

    Public Sub LockWay()
        If mEntered Then Throw New SynchronizationLockException("ещё сами не вышли, а уже всех выгоняем!")
        Monitor.Enter(Me)
        While mCount > 0 ' если поток помер, не вызвав LeaveWay, то это не наши проблемы, а его.
            OneGone.WaitOne() ' (вновь подражаем обычному семафору)
            OneGone.Reset()
        End While
    End Sub
    Public Sub UnlockWay()
        Monitor.Exit(Me)
    End Sub
End Class
Изображение


Вернуться в Наши проекты

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 38

    TopList