Форум: "Прочее";
Текущий архив: 2011.11.27;
Скачать: [xml.tar.bz2];
Внизthreadvar Найти похожие ветки
← →
Дмитрий С © (2011-07-28 17:29) [0]Кто нибудь это использует?:)
← →
Игорь Шевченко © (2011-07-28 17:49) [1]Да
← →
DiamondShark © (2011-07-28 18:04) [2]Вопрос, надо полагать, закрыт. ;)
← →
DVM © (2011-07-28 18:13) [3]Раньше не использовал пока не попалось в одном проекте. В такой переменной удобно хранить имя потока, например, для отладки.
← →
DVM © (2011-07-28 18:17) [4]Вот, например:
////////////////////////////////////////////////////////////////////////////////
//
// ****************************************************************************
// * Модуль : uNamedThread.pas
// * Назначение : Расширение базового класса TThread с возможностью
// * : создания именованных потоков
// * Copyright : 2011 © Дмитрий Муратов
// ****************************************************************************
//
unit uNamedThread;
interface
uses
Windows, Classes, SysUtils;
type
{$REGION "Documentation"}
/// <summary>
/// Класс именованного потока
/// </summary>
{$ENDREGION}
TNamedThread = class(TThread)
private
FThreadName: String;
procedure SetName(const AValue: String);
public
{$REGION "Documentation"}
/// <summary>
/// Назначает имя вызывающему потоку
/// </summary>
/// <param name="AThreadName">Имя потока</param>
/// <param name="AThreadID">ID потока</param>
/// <remarks>
/// см. http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.71).aspx
/// </remarks>
{$ENDREGION}
class procedure SetThreadName(AThreadName: String; AThreadID: LongWord = LongWord(-1)); static;
{$REGION "Documentation"}
/// <summary>
/// Возвращает имя вызывающего потока, при условии,
/// что к нему применялась ранее функция SetThreadName (см.выше)
/// Если имя потоку не назначено, то возвращается его ID в виде HEX строки
/// </summary>
{$ENDREGION}
class function GetCurentThreadName: string; static;
property ThreadName: String read FThreadName write SetName;
end;
implementation
threadvar
_InternalThreadName: String;
//------------------------------------------------------------------------------
class procedure TNamedThread.SetThreadName(AThreadName: String; AThreadID: LongWord = LongWord(-1));
{$IFDEF MSWINDOWS}
type
TThreadNameInfo = record
InfoType: LongWord; // Всегда 0x1000
Name: PChar; // Имя потока
ThreadID: LongWord; // Thread ID (-1 ($FFFFFFFF)для вызывающего потока)
Reserved: LongWord; // Зарезервировано
end;
const
cSetThreadNameExcep = $406D1388;
DefaultInfoType = $1000;
var
ThreadNameInfo: TThreadNameInfo;
begin
FillChar(ThreadNameInfo, SizeOf(ThreadNameInfo), 0);
ThreadNameInfo.InfoType := DefaultInfoType;
ThreadNameInfo.Name := PChar(AThreadName);
if (AThreadID = Cardinal(-1)) or (AThreadID = GetCurrentThreadID) then
_InternalThreadName := AThreadName;
ThreadNameInfo.ThreadID := AThreadID;
try
RaiseException(cSetThreadNameExcep, 0, SizeOf(ThreadNameInfo) div SizeOf(LongWord),
@ThreadNameInfo);
except
//
end;
end;
{$ENDIF}
{$IFDEF LINUX}
begin
end;
{$ENDIF}
//------------------------------------------------------------------------------
class function TNamedThread.GetCurentThreadName: string;
begin
Result := _InternalThreadName;
if Length(Result) = 0 then
Result := "0x"+ IntToHex(GetCurrentThreadID, 8);
end;
//------------------------------------------------------------------------------
procedure TNamedThread.SetName(const AValue: String);
begin
if FThreadName <> AValue then
begin
FThreadName := AValue;
SetThreadName(FThreadName, ThreadID);
end;
end;
end.
← →
Jeer © (2011-07-28 18:19) [5]
> Кто нибудь это использует?:)
Только помнить, что эта секция не делает потоко-безопасными переменные в ней описанные.
← →
Dimka Maslov © (2011-07-28 18:30) [6]предпочитаю использовать более прозрачные способы разделения ресурсов в потоках.
← →
oxffff © (2011-07-28 21:21) [7]Да.
← →
Loginov Dmitry © (2011-07-28 21:58) [8]
> Кто нибудь это использует?:)
Разумеется, что хоть кто-нибудь это использует, иначе для какой цели оно было введено в состав языка. Другое дело, использует ли это кто-нибудь из здешних на практике :)
Ответ "Да". Разок где-то приходилось использовать :)
← →
han_malign (2011-07-29 11:07) [9]MS - сплошь и рядом TLS использует(для часто используемых временных буферов в основном)...
← →
RWolf © (2011-07-29 13:27) [10]это может дать какой-нибудь теоретический профит по сравнению с приватными полями потомка TThread, например?
← →
DVM © (2011-07-29 14:06) [11]
> RWolf © (29.07.11 13:27) [10]
> это может дать какой-нибудь теоретический профит по сравнению
> с приватными полями потомка TThread, например?
Допустим, есть некая функция, выполняющийся в контексте какого то потока, но сам поток не является порождением класса TThread (поток вообще может быть чужой, но функцию вызывает твою). Надо как то допустим логгировать по ходу выполнения функции необходимые действия, но так, чтобы для разных потоков строки в логе отличались.
Одно из решений таково - ты заводишь глобальную threadvar переменную и присваиваешь ей имя потока (в примере выше у меня это делается через class procedure SetThreadName).
И допустим у тебя есть какой то логгер, который пишет в лог кроме всего прочего значение этой переменной (в моем случае логгер обращается к классовой функции class function GetCurentThreadName). И все. Даже если потоки чужие, мы имеем некие данные к ним привязанные.
← →
Игорь Шевченко © (2011-07-29 15:25) [12]
> это может дать какой-нибудь теоретический профит по сравнению
> с приватными полями потомка TThread, например?
сколько угодно профита
← →
DiamondShark © (2011-07-29 15:34) [13]
> это может дать какой-нибудь теоретический профит
Посмотри, как ведёт себя GetLastError, например.
> по сравнению с приватными полями потомка TThread, например?
У тебя есть библиотека, неООПная, с состоянием.
Где ты потомка TThread возмёшь?
← →
DVM © (2011-08-02 13:52) [14]Кстати, недавно обнаружил, что threadvar строки образуют утечки памяти в программе (Под Delphi XE точно, по крайней мере):
program Leak;
{$APPTYPE CONSOLE}
threadvar
s: string;
begin
ReportMemoryLeaksOnShutdown := True;
s := "Leak";
// ... bla-bla-bla
end.
Для того, чтобы пофиксить, надо:program NoLeak;
{$APPTYPE CONSOLE}
threadvar
s: string;
begin
ReportMemoryLeaksOnShutdown := True;
s := "NoLeak";
// ... bla-bla-bla
s := "";
end.
← →
DiamondShark © (2011-08-02 15:05) [15]
> DVM © (02.08.11 13:52) [14]
Анекдот вспомнил.
Приходит бабка к доктору и говорит:
-- Доктор, когда я вот так (достаёт левой рукой правое ухо из-за спины) делаю, у меня вот тут (показывает на правую ягодицу) стреляет.
-- А вы так не делайте -- говорит доктор.
> Кстати, недавно обнаружил, что threadvar строки образуют
> утечки памяти в программе (Под Delphi XE точно, по крайней
> мере):
Это не баг, это фича. Ну не приделан к главному блоку финализатор TLS. И правильно сделано, что не приделан -- нефиг энтропию Вселенной повышать.
В потоках же всё нормально работает? Вот и не делайте так.
← →
DVM © (2011-08-02 17:18) [16]
> DiamondShark © (02.08.11 15:05) [15]
> В потоках же всё нормально работает?
Нет, в потоках тоже не нормально.
← →
DiamondShark © (2011-08-02 17:21) [17]
> Нет, в потоках тоже не нормально.
Правда? В RTL-ной обёртке функции потока нет финализации TLS?
Жаль. Хороший был язык.
← →
Дмитрий Тимохов (2011-08-03 23:25) [18]вроде как tls не оч. быстр.
вот где-то в реализации мулти реад ексклюзив райт (не помню как класс точно называется) есть об этом замечание и своя реализация tls.
← →
DiamondShark © (2011-08-04 11:12) [19]
> Дмитрий Тимохов (03.08.11 23:25) [18]
> вроде как tls не оч. быстр.
С чего бы это вдруг?
Страницы: 1 вся ветка
Форум: "Прочее";
Текущий архив: 2011.11.27;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.004 c