Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2008.05.11;
Скачать: [xml.tar.bz2];

Вниз

оцените пожалуйста код   Найти похожие ветки 

 
@!!ex ©   (2008-03-25 21:19) [0]

Сейчас встала задача распаралеливания вычислений. Она уже несколько раз вставала, но раньше удавалось ее обходить. Теперь вопрос встал ребром...

Написал вот модуль, для работы с потоками. Но так как в теме еще понимаю мало, хочеться узнать, насколько правильно я его написал.

unit uThread;

interface
uses
    Windows;

type
 TCriticalSection = class
 private
   FSection:_RTL_CRITICAL_SECTION;
 public
   Constructor Create;
   Destructor  Destroy; override;
   Procedure   Enter;
   Procedure   Leave;
 end;

 TSemaphore = class
 private
   FSemaphore:Cardinal;
 public
   Constructor Create;
   Destructor  Destroy; override;
   Procedure   Enter;
   Function    TryEnter:boolean;
   Procedure   Leave(Count:integer = 1);
 end;

 TThread = class
 protected
   FStateTHRead:integer;
   FIsTerminated:boolean;
   FThread:integer;
   FLock:TCriticalSection;
   Function    StateThread:integer;
   Function    StartThread(IsSuspend:boolean = true):boolean;
 public
   Constructor Create(IsSuspend:boolean = true);
   Destructor  Destroy; override;
   Procedure   Execute; virtual; abstract;
   Procedure   Wait;
   Procedure   Suspend;
   Procedure   Resume;
   Procedure   Terminate;
   Function    Terminated:boolean;
   property    Lock:TCriticalSection read FLock;
 end;

implementation

{ TCriticalSection }

constructor TCriticalSection.Create;
begin
 InitializeCriticalSection(FSection);
end;

destructor TCriticalSection.Destroy;
begin
 DeleteCriticalSection(FSection);
 inherited;
end;

procedure TCriticalSection.Enter;
begin
 EnterCriticalSection(FSection);
end;

procedure TCriticalSection.Leave;
begin
 LeaveCriticalSection(FSection);
end;

{ TSemaphore }

constructor TSemaphore.Create;
begin
 FSemaphore := CreateSemaphore(nil, 0, 100000000, nil);
end;

destructor TSemaphore.Destroy;
begin
 CloseHandle(FSemaphore);
 inherited;
end;

procedure TSemaphore.Enter;
begin
 WaitForSingleObject(FSemaphore, INFINITE);
end;

procedure TSemaphore.Leave(Count: integer);
begin
 ReleaseSemaphore(FSemaphore, Count, nil);
end;

function TSemaphore.TryEnter: boolean;
begin
 Result:=not WaitForSingleObject(FSemaphore, 0)=WAIT_TIMEOUT;
end;

const
 ST_NONE    = 0;
 ST_SUSPEND = 1;
 ST_RESUME  = 2;
 ST_STOP    = 3;

function ObjectNewTHRead(lpThreadParameter: TThread): Integer; stdcall;
begin
 lpThreadParameter.Execute();
 lpThreadParameter.Lock.Enter();
 lpThreadParameter.FStateTHRead := ST_STOP;
 lpThreadParameter.Lock.Leave();
 Result:=0;
end;

{ TThread }

constructor TThread.Create(IsSuspend: boolean);
begin
 FIsTerminated := false;
if IsSuspend then
   FStateTHRead:=ST_SUSPEND
else
   FStateTHRead:=ST_RESUME;

if not StartThRead(IsSuspend) then
   FStateTHRead:=ST_NONE;
end;

destructor TThread.Destroy;
begin
Terminate();
Wait();
 inherited;
end;

procedure TThread.Resume;
begin
Lock.Enter();
 if FStateTHRead = ST_SUSPEND then begin
 ResumeThread(FTHRead);
 FStateTHRead := ST_RESUME;
 end;
 Lock.Leave();
end;

function TThread.StartThread(IsSuspend: boolean): boolean;
var
 dwTHID:cardinal;
begin
if IsSuspend then
   FThread:=CreateThread(nil,100000,@ObjectNewTHRead,self,CREATE_SUSPENDED,dwTHID)
else
  FThread:=CreateThread(nil,100000,@ObjectNewTHRead,self,0,dwTHID);
 Result:=FThread<>0;
end;

function TThread.StateThread: integer;
begin
 Lock.Enter();
 Result := FStateTHRead;
 Lock.Leave();
end;

procedure TThread.Suspend;
begin
Lock.Enter();
if FStateTHRead=ST_RESUME then begin
  SuspendThread(FTHRead);
 FStateTHRead := ST_SUSPEND;
 end;
Lock.Leave();
end;

procedure TThread.Terminate;
begin
 Lock.Enter();
 FIsTerminated := TRUE;
 Lock.Leave();
 Resume();
end;

function TThread.Terminated: boolean;
begin
 Lock.Enter();
 Result := FIsTerminated;
 Lock.Leave();
end;

procedure TThread.Wait;
begin
 if StateTHRead()<>ST_NONE then begin
   WaitForSingleObject(FTHRead,INFINITE);
   CloseHandle(FTHRead);
 end;
 FStateTHRead := ST_NONE;
end;

end.


 
Джо ©   (2008-03-25 21:20) [1]

Даже не глядя в код, спрошу — а зачем создавать свой TCriticalSection, если оный уже есть в VCL?


 
Джо ©   (2008-03-25 21:21) [2]

И остальные тоже...


 
@!!ex ©   (2008-03-25 21:23) [3]

> а зачем создавать свой TCriticalSection, если оный уже есть
> в VCL?

Ну во-первых я не знал что в VCL это уже есть. :)
А во-вторых - использование VCL нельзя использовать, т.к. проект планируется компилять под FPC, и возможно переписывать под C++.


 
Informer   (2008-03-25 21:31) [4]

> @!!ex ©   (25.03.08 21:23) [3]
А почему бы сразу не писАть на С++?


 
DVM ©   (2008-03-25 21:32) [5]


> procedure TThread.Terminate;
> begin
>  Lock.Enter();
>  FIsTerminated := TRUE;
>  Lock.Leave();
>  Resume();
> end;

ИМХО критические секции тут вообще лишние.

Вот предложу такой вариант:


unit Threads;

interface

uses Windows;

////////////////////////////////////////////////////////////////////////////////
// TThread
////////////////////////////////////////////////////////////////////////////////

type

 TThreadMethod = procedure of object;
 TThreadPriority = (tpIdle, tpLowest, tpLower, tpNormal, tpHigher, tpHighest,
   tpTimeCritical);

const

 Priorities: array [TThreadPriority] of Integer =
   (THREAD_PRIORITY_IDLE,
    THREAD_PRIORITY_LOWEST,
    THREAD_PRIORITY_BELOW_NORMAL,
    THREAD_PRIORITY_NORMAL,
    THREAD_PRIORITY_ABOVE_NORMAL,
    THREAD_PRIORITY_HIGHEST,
    THREAD_PRIORITY_TIME_CRITICAL);

type

 TThread = class
 private
   FHandle: THandle;
   FThreadID: THandle;
   FTerminated: Boolean;
   FSuspended: Boolean;
   FFreeOnTerminate: Boolean;
   FFinished: Boolean;
   FReturnValue: DWORD;
   function GetPriority: TThreadPriority;
   procedure SetPriority(Value: TThreadPriority);
   procedure SetSuspended(Value: Boolean);
 protected
   procedure Execute; virtual; abstract;
   property ReturnValue: DWORD read FReturnValue write FReturnValue;
   property Terminated: Boolean read FTerminated;
 public
   constructor Create(CreateSuspended: Boolean);
   destructor Destroy; override;
   procedure Resume;
   procedure Suspend;
   procedure Terminate;
   procedure WaitFor;
   property FreeOnTerminate: Boolean read FFreeOnTerminate write FFreeOnTerminate;
   property Handle: THandle read FHandle;
   property Priority: TThreadPriority read GetPriority write SetPriority;
   property Suspended: Boolean read FSuspended write SetSuspended;
   property ThreadID: THandle read FThreadID;
 end;

implementation

////////////////////////////////////////////////////////////////////////////////
// TThread
////////////////////////////////////////////////////////////////////////////////

function ThreadProc(Thread: TThread): DWORD;
var
 FreeThread: Boolean;
begin
 Thread.Execute;
 FreeThread := Thread.FFreeOnTerminate;
 Result := Thread.FReturnValue;
 Thread.FFinished := True;
 if FreeThread then Thread.Free;
 EndThread(Result);
end;

//------------------------------------------------------------------------------

constructor TThread.Create(CreateSuspended: Boolean);
var
 Flags: DWORD;
begin
 inherited Create;
 FSuspended := CreateSuspended;
 Flags := 0;
 if CreateSuspended then Flags := CREATE_SUSPENDED;
 FHandle := BeginThread(nil, 0, @ThreadProc, Pointer(Self), Flags, FThreadID);
end;

//------------------------------------------------------------------------------

destructor TThread.Destroy;
begin
 if FHandle <> 0 then CloseHandle(FHandle);
 inherited Destroy;
end;

//------------------------------------------------------------------------------

function TThread.GetPriority: TThreadPriority;
var
 P: Integer;
 I: TThreadPriority;
begin
 P := GetThreadPriority(FHandle);
 Result := tpNormal;
 for I := Low(TThreadPriority) to High(TThreadPriority) do
   if Priorities[I] = P then Result := I;
end;

//------------------------------------------------------------------------------

procedure TThread.SetPriority(Value: TThreadPriority);
begin
 SetThreadPriority(FHandle, Priorities[Value]);
end;

//------------------------------------------------------------------------------

procedure TThread.SetSuspended(Value: Boolean);
begin
 if Value <> FSuspended then
   if Value then
     Suspend
   else
     Resume;
end;

//------------------------------------------------------------------------------

procedure TThread.Suspend;
begin
 FSuspended := True;
 SuspendThread(FHandle);
end;

//------------------------------------------------------------------------------

procedure TThread.Resume;
begin
 if ResumeThread(FHandle) = 1 then FSuspended := False;
end;

//------------------------------------------------------------------------------

procedure TThread.Terminate;
begin
 FTerminated := True;
end;

//------------------------------------------------------------------------------

procedure TThread.WaitFor;
begin
 WaitForSingleObject(FHandle, INFINITE);
end;

//------------------------------------------------------------------------------

end.



 
ага   (2008-03-25 21:33) [6]


> constructor TThread.Create(IsSuspend: boolean);
> begin
>  FIsTerminated := false;


> procedure TThread.Terminate;
> begin
>  Lock.Enter();
>  FIsTerminated := TRUE;

Нафига??


 
ага   (2008-03-25 21:36) [7]


> DVM ©   (25.03.08 21:32) [5]


> procedure TThread.Terminate;
> begin
>  FTerminated := True;
> end;

Аналогично - нафига?


 
@!!ex ©   (2008-03-25 21:37) [8]

> [6] ага   (25.03.08 21:33)

В Execute следишь за состоянием FIsTerminated, если true - выходим.


> ИМХО критические секции тут вообще лишние.

А вдруг присвоение не атомарное? :)


 
DVM ©   (2008-03-25 21:40) [9]


> ага   (25.03.08 21:36) [7]


> Аналогично - нафига?

Не понимаю вопроса. Что смущает? Выставляется флаг завершения, процедура, которая будет крутиться в методе Execute должна проверять состояние флага.


> А вдруг присвоение не атомарное? :)

Даже если не атомарное ничего не случится.


 
@!!ex ©   (2008-03-25 21:40) [10]

> [4] Informer   (25.03.08 21:31)

А смысл?
Я на дельфи быстрее пишу и качесвтенней.


 
DVM ©   (2008-03-25 21:43) [11]


> Я на дельфи быстрее пишу и качесвтенней.

На Delphi вообще все пишут качественнее. Я вот тут месяц с лишним писал на си (без плюсов) для некоего девайса (даже на неком подмножестве турбо си). Отсутствие типа строка просто убивало. Мало того, что неудобно, так еще и очень очень внимательным надо быть, чтобы не дай бог не вылезти за границы массива или \0 не забыть где.


 
ага   (2008-03-25 21:46) [12]


> @!!ex ©   (25.03.08 21:37) [8]


> DVM ©   (25.03.08 21:40) [9]

У tthread уже есть terminated. Зачем самодеятельность?


 
DVM ©   (2008-03-25 21:49) [13]


> У tthread уже есть terminated. Зачем самодеятельность?

У кого есть? Этот код рассматривается как раз как альтернатива классу TThread из Classes. К тому же terminated стандартного класса TThread это не то же самое, что terminate того же класса.


 
ага   (2008-03-25 21:54) [14]


> DVM ©   (25.03.08 21:49) [13]
>
>
> > У tthread уже есть terminated. Зачем самодеятельность?
>
>
> У кого есть? Этот код рассматривается как раз как альтернатива
> классу TThread из Classes. К тому же terminated стандартного
> класса TThread это не то же самое, что terminate того же
> класса.

terminated - тот же флаг. Terminate тоже выставляет значение этого флага, но никто не
мешает вручную безболезненно выставлять этот флаг аналогично [0] и [5].
И зачем вообще велосипеды изобретать?


 
Игорь Шевченко ©   (2008-03-25 21:57) [15]


> Написал вот модуль, для работы с потоками. Но так как в
> теме еще понимаю мало


А TThread использовать религия не велит ?


 
DVM ©   (2008-03-25 21:59) [16]


> но никто не
> мешает вручную безболезненно выставлять этот флаг аналогично
> [0] и [5].

Мешает, ибо:

property Terminated: Boolean read FTerminated;


> И зачем вообще велосипеды изобретать?

Затем, чтобы использовать FreePascal и не использовать модуль Classes например. К тому же можно создать более гибкую и более удобную реализацию обертки под поток, чем в Classes.


 
ага   (2008-03-25 22:09) [17]


> DVM ©   (25.03.08 21:59) [16]
>
>
> > но никто не
> > мешает вручную безболезненно выставлять этот флаг аналогично
> > [0] и [5].
>
> Мешает, ибо:

Не мешает.
И, к стати, в FCL тоже есть tthread.


 
Mystic ©   (2008-03-25 22:14) [18]


> А во-вторых - использование VCL нельзя использовать, т.к.
>  проект планируется компилять под FPC, и возможно переписывать
> под C++.


Насколько я знаю, под FPC есть классы, аналогичные VCL. Причем реализованные как под Win, так и под *nix. В крайнем случае можно скопировать реализацию из VCL, или взять ее за основу :)

Во-вторых, есть много различных библиотек под C++, где это все уже реализовано, да еще в кроссплатформенном виде :)

В-третьих, мало кому интересны обвертки над VCL. Вот если бы ты описал свою задачу и с помочу чего и как т ыхочешь распараллелить.. А так... Это техника...

В четвертых, Lock.Enter и Lock.Leave надо оборачивать в try..finally

В пятых, функцией CreateThread пользоваться низзя, надо использовать BeginThread. Основная причина в том, что BeginThread устанавливает переменную IsMultyThread в True. А она используется, например, в менеджере памяти (надо или не надо входить в критическую секцию). Поэтому могут быть труднонаходимые проблемы. Конечно, если код потока не испольуется строк и других объектов с автоматическим управлением памятью, то можно и CreateThread вызвать...

В шестых, константы состояния потока закрыты (implementation), а функция StateThread обкрыта (protected).

В седьмых, CloseHandle для потока лучше перенести в деструктор. Теоретически (1) поток можно ждать и после его завершения, (2) Wait могут вызвать разные потоки

Ну и далее общее пожелание:

>> DVM ©   (25.03.08 21:32) [5]

Очень часто поток валится из-за исключения. В этом случае он просто убивается и все. В твоем случае ты об этом так и не узнаешь. Посему правильнее было бы написать:


function ThreadProc(Thread: TThread): DWORD;
var
FreeThread: Boolean;
begin
 try
  Thread.Execute;
 except
   on E: Exceptions do
     Windows.MessageBox(...); // Хотя-бы вывести отладочное сообщение
     // Другая нужная обработка
 end;

 try
  FreeThread := Thread.FFreeOnTerminate;
  Result := Thread.FReturnValue;
  Thread.FFinished := True;
  if FreeThread then Thread.Free;
  EndThread(Result);
 except
   on E: Exceptions do
     // А сюда мы можем попасть если некто сделал Free() данному потоку в момент его работы.
     // Тоже желательно провести диагностику
 end;
end;


 
DVM ©   (2008-03-25 22:15) [19]


> Не мешает.

Я тебе привел строчку из класса TTread модуля Classes.

property Terminated: Boolean read FTerminated;

Из нее следует, что свойство Terminated только для чтения. И создав экземпляр этого класса, ты не сможешь извне менять состояние свойства напрямую, а только через метод Terminate. Неужели непонятно?

Ясен пень, что можно написать и по другому и вооюще несколькими способами. Но так уж повелось, что некоторые объекты имеют свойства и методы меняющие эти свойства. Иногда даже если свойства не только для чтеня. Например свойство Active и Connect у оберток под сокеты.


> И, к стати, в FCL тоже есть tthread.

Ты это не мне доказывай, а автору вопроса, меня вообще и стандартный TThread устраивает.


 
Игорь Шевченко ©   (2008-03-25 22:22) [20]


> и не использовать модуль Classes например


А что, использование модуля Classes considered harmful ?


 
ага   (2008-03-25 22:24) [21]


> DVM ©   (25.03.08 22:15) [19]
>
>
> > Не мешает.
>
> Я тебе привел строчку из класса TTread модуля Classes.

А нет у меня D. По памяти пишу. И, на сколько помню - в terminate ничего кроме
выставления terminated=true не делается. Этого достаточно.

> Ты это не мне доказывай, а автору вопроса

Я никому ничего не доказываю. Просто дискуссия.


 
DVM ©   (2008-03-25 22:29) [22]


> Игорь Шевченко ©   (25.03.08 22:22) [20]
>
> > и не использовать модуль Classes например
>
>
> А что, использование модуля Classes considered harmful

Какой Classes может быть под  FreePascal? Даже, если он там и скомпилируется, то все равно это нарушение лицензии.


 
Игорь Шевченко ©   (2008-03-25 22:31) [23]

DVM ©   (25.03.08 22:29) [22]

Я снес FreePascal вместе с lazarus, так что ничего не могу сказать на этот предмет. А что, и модуля SysUtils там нету ? :)


 
DVM ©   (2008-03-25 22:34) [24]


> А что, и модуля SysUtils там нету ? :)

Я понятия не имею, не использовал FreePascal толком. Lazarus же вообще оставил впечатление жуткой недоработки. Но тем не менее они есть и, в отличие от Delphi могут компилировать под разные платформы, в том числе и под 64 bit.


 
Mystic ©   (2008-03-25 22:38) [25]


>
> Какой Classes может быть под  FreePascal? Даже, если он
> там и скомпилируется, то все равно это нарушение лицензии.


Свой собственный, немного расширенный, портированный под Linux.


 
ага   (2008-03-25 22:39) [26]


> DVM ©   (25.03.08 22:29) [22]
>
> Какой Classes может быть под  FreePascal?

Поставь уже FPC и посмотри какой.


 
DVM ©   (2008-03-25 22:42) [27]


> Свой собственный

Свой понятно, что там есть. Но речь, насколько я понял, изначально шла о том, чтобы одно и то же приложение могло с одинаковым успехом компилироваться и в Delphi и во FreePascal. Такое наверняка проще обеспечить, если создать свою обертку под поток, а не использовать возможно сильно отличающиеся классы из разных модулей Classes.


 
DVM ©   (2008-03-25 22:44) [28]


> Поставь уже FPC и посмотри какой.

Зачем мне на него смотреть. Ты просто не понял моей фразы. Надо читать как "Какой модуль Classes из Delphi может быть во FreePascal".


 
ага   (2008-03-25 22:52) [29]


> DVM ©   (25.03.08 22:44) [28]

Из D? портированный... Можно сказать самодельный.
Там есть и tstream и tstrings и tstringlist и почти все, что есть в classes delphi.
Почти-это имхо, потому что я не особо интересуюсь и всех тонкостей не знаю.


 
DiamondShark ©   (2008-03-25 23:53) [30]


> К тому же можно создать более гибкую и более удобную реализацию
> обертки под поток

Обёртки для таких примитивных сущностей -- это верх маразма.
А использование слова-паразита "гибкую" -- тревожный симптом повышенной толерантности к маркетоложеству.

Попытка создания "гибкости" вокруг примитивной вещи приводит к нагромождению кода, к "протекающим абстракциям" и, в конце концов, к потере той самой "гибкости", за которую боролись.


 
DVM ©   (2008-03-26 00:01) [31]


> Обёртки для таких примитивных сущностей -- это верх маразма.

Значит в борланде одни маразматики.


> Попытка создания "гибкости" вокруг примитивной вещи

Насчет примитивности задачи создания обертки для потока не согласен категорически.


> Попытка создания "гибкости" вокруг примитивной вещи приводит
> к нагромождению кода

Гибкость и размер кода никак не связаны между собой.


> А использование слова-паразита "гибкую"

Первый раз слышу о таком слове "паразите".


 
DVM ©   (2008-03-26 00:05) [32]


> Обёртки для таких примитивных сущностей -- это верх маразма.

У меня почему то складывается такое ощущение, что вы никогда не работали над многопоточными риложениями. Странные рассуждения какие то.


 
Anatoly Podgoretsky ©   (2008-03-26 00:40) [33]

> DVM  (25.03.2008 22:15:19)  [19]

> Из нее следует, что свойство Terminated только для чтения. И создав экземпляр этого класса, ты не сможешь извне менять состояние свойства напрямую, а только через метод Terminate.

Что бы не выстрелить себе в ногу.


 
Anatoly Podgoretsky ©   (2008-03-26 00:43) [34]

> DiamondShark  (25.03.2008 23:53:30)  [30]

Красиво излагаешь.


 
DiamondShark ©   (2008-03-26 12:29) [35]


> DVM ©   (26.03.08 00:01) [31]
>
> > Обёртки для таких примитивных сущностей -- это верх маразма.
>
> Значит в борланде одни маразматики.

Странный вывод. Ви, таки, намекаете, что Борланд не написал ничего, кроме обёрток над простыми вещами?


> > Попытка создания "гибкости" вокруг примитивной вещи
>
> Насчет примитивности задачи создания обертки для потока
> не согласен категорически.

Будете смеяться, но я тоже. Задачу можно себе наворотить как угодно, было бы желание. Кто ж тут спорит?
Но, видите ли, я нигде не говорил о примитивности задачи создания обертки, я говорил о примитивной вещи. Поток -- вещь примитивная (говорим, конечно, не о потрохах ядра, а об уровне прикладного ПО). Есть возражения?


> Гибкость и размер кода никак не связаны между собой.

Увы, связаны. Даже у очень простой вещи может быть множество сценариев использования. Гибкая обёртка должна предусматривать их либо все, либо большинство, либо, хотя бы, значительную часть, иначе она уже не будет гибкой, или не будет обёрткой. Если обёртка не прусматривает какого-либо интересного сценария, ей будет невозможно пользоваться, потому что хорошая непротекающая обёртка тщательно скрывает детали реализации. Или обёртка вынуждена предоставлять какие-нибудь хуки-хаки, вроде выставления public-свойством Handle оборачиваемого объекта. И то и другое оборачивается мусорным кодом: либо неиспользуемым библиотечным, либо пользовательскими костылями.
А если оборачиваемая сущность достаточно проста (как в случае потока), то обёртка, в наименее патологическом случае, вырождается в пересказ низлежащего API другими словами. Но в этом случае теряется сам смысл обертки: никакая новая абстракция не вводится, ни объём, ни сложность прикладного кода не меняются (хе-хе;) если не увеличиваются). Посмотрите, чего полезного вносит использование класса TThread вместо BeginThread? Да ничего.


> Первый раз слышу о таком слове "паразите".

Да ладно! Сплошь и рядом слышатся уверения, что-де такой-то программный продукт "гибкий". Как правило, в переводе на русский это означает что продукт монстроузный, с мутной логикой и требующий обработки напильником перед сколь-нибудь продуктивным использованием.


> У меня почему то складывается такое ощущение, что вы никогда
> не работали над многопоточными риложениями. Странные рассуждения
> какие то.

У меня, почему-то, SKLадывается ощущение, что Вы, таки, решили перейти на личности, не въехав толком в рассуждения.


 
@!!ex ©   (2008-03-26 12:53) [36]

> Увы, связаны. Даже у очень простой вещи может быть множество
> сценариев использования. Гибкая обёртка должна предусматривать
> их либо все, либо большинство, либо, хотя бы, значительную
> часть, иначе она уже не будет гибкой, или не будет обёрткой.
> Если обёртка не прусматривает какого-либо интересного сценария,
> ей будет невозможно пользоваться, потому что хорошая непротекающая
> обёртка тщательно скрывает детали реализации. Или обёртка
> вынуждена предоставлять какие-нибудь хуки-хаки, вроде выставления
> public-свойством Handle оборачиваемого объекта. И то и другое
> оборачивается мусорным кодом: либо неиспользуемым библиотечным,
> либо пользовательскими костылями.
> А если оборачиваемая сущность достаточно проста (как в случае
> потока), то обёртка, в наименее патологическом случае, вырождается
> в пересказ низлежащего API другими словами. Но в этом случае
> теряется сам смысл обертки: никакая новая абстракция не
> вводится, ни объём, ни сложность прикладного кода не меняются
> (хе-хе;) если не увеличиваются). Посмотрите, чего полезного
> вносит использование класса TThread вместо BeginThread?
> Да ничего.

Да ун ерунду говорите.
Интерфейс нужен хотя бы для того, чтобы избавиться от процедурного программирования.
ООП нагляднее однако. Поток легче контролировать. Нигде не надо хранить идентефикатор потока и т.д.


 
Игорь Шевченко ©   (2008-03-26 13:19) [37]


> Да ун ерунду говорите.
> Интерфейс нужен хотя бы для того, чтобы избавиться от процедурного
> программирования.
> ООП нагляднее однако. Поток легче контролировать. Нигде
> не надо хранить идентефикатор потока и т.д.


Это вы ерунду говорите. Уж извините, но это так.


 
Mystic ©   (2008-03-26 13:20) [38]

> Но речь, насколько я понял, изначально шла о том, чтобы
> одно и то же приложение могло с одинаковым успехом компилироваться
> и в Delphi и во FreePascal.


Classes во FreePascal совместим с Delphi. Обратное, вообще говоря, не верно.

> Обёртки для таких примитивных сущностей -- это верх маразма.

Цели обверток:
 (1) Придать программе единообразную структуру. Если у нас используются только объекты, то обращения к нативному API немного режут глаз.
 (2) Завязка на кроссплатформенность. Если остальной код никак не завязан на особенности OS, то потратил вечер на написание обверток, то в будущем для портирования под другую OS мне понадобится тоже один вечер :)
 (3) Type mapping. Постоянные приведения от string к PChar захламляют код. Точно так же и возвращаемые значения
 (4) В обвертках также реализовываются наиболее часто встречающиеся сценарии использования объектов. Например, ты сравнивал TThread и BeginThread. Хорошо, отвечу на вопрос, какие преимущества дает стандартный TThread:
   (a) Контекст потока. Внутри потомка класса TThread мы можем объявить кучу полей, которые будут в дальнейшем легко доступны во всех вызовах методов TThread. В случае BeginThread контекст прийдется создавать самому: определять структуру, объявлять переменную ctx типа указанной структуры, при всех вызовах передавать эту переменную, любое обращение к переменной контекста предварять ctx. и т. п.
   (b) Метод Synchronize
   (c) Стандартный механизм для прерывания вычислений потока. Конечно, я бы предпочел возможность передачи различных сигналов потоку (например, terminate), после чего поток мог бы возбудить исключение, которое я бы обработал в Execute. Или написать функцию вроде RaiseExceptionInThread(Thread: THandle; E: Exception). Но все равно стандартный часто используемый механизм есть.


 
Eraser ©   (2008-03-26 13:22) [39]


> DiamondShark ©   (26.03.08 12:29) [35]

да ООП это вообще зло, а C# - недоязык )


 
Игорь Шевченко ©   (2008-03-26 13:27) [40]

"ОО-языки упрощают абстракцию, возможно, даже слишком ее упрощают. Они поддерживают создание структур с большим количеством связующего кода и сложными уровнями.
Это может оказаться полезным в случае, если предметная область является
действительно сложной и требует множества абстракций, и вместе с тем такой подход может обернуться неприятностями, если программисты реализуют простые вещи сложными способами, просто потому что им известны эти способы и они умеют ими пользоваться.
Все ОО-языки несколько сколнны "втягивать" программистов в ловушку избыточной иерархии. Чрезмерное количество уровней разрушает прозрачность: крайне затрудняется их просмотр и анализ ментальной модели, которую по существу реализует код. Всецело нарушаются правила простоты, ясности и прозрачности, а в результате код наполняется скрытыми ошибками и создает постоянные проблемы при сопровождении.
Данная тенденция, вероятно, усугубляется тем, что множество курсов по
программированию преподают громоздкую иерархию как способ удовлетворения правила представления. С этой точки зрения множество классов приравнивается к внедрению знаний в данные. Проблема данного подхода заключается в том, что слишком часто "развитые данные" в связующих уровнях фактически не относятся у какому-либо естественному объекту в области действия программы - они предназначены только для связующего уровня.
Одной из причин того, что ОО-языки преуспели в большинстве характерных для них предметных областей (GUI-интерфейсы, моделирование, графические средства), возможно, является то, что в этих областях относительно трудно неправильно определить онтологию типов. Например, в GUI-интерфейсах и графических средствах присутствует довольно естественное соотвествие между манипулируемыми визуальными объектами и классами. Если выясняется, что создается большое количество классов, которые не имеют очевидного соответствия с тем, что
происходит на экране, то, соотвественно, легко заметить, что связующий уровень стал слишком большим."

(с) Эрик Реймонд, "Искусство программирования для Unix"



Страницы: 1 2 вся ветка

Форум: "Прочее";
Текущий архив: 2008.05.11;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.61 MB
Время: 0.008 c
2-1207753937
Омск
2008-04-09 19:12
2008.05.11
Перевод миль в километры


9-1169828083
maxProg
2007-01-26 19:14
2008.05.11
Модели и текстуры


4-1188388045
ElectriC
2007-08-29 15:47
2008.05.11
Экранная заставка


2-1208170710
djaUser
2008-04-14 14:58
2008.05.11
Загрузка файлов с инет.


2-1207926538
Снежинка
2008-04-11 19:08
2008.05.11
Запрос





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский