Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 09.01.2013, 19:44   #1
alexprey
Форумчанин
 
Регистрация: 25.05.2010
Сообщений: 169
По умолчанию Указатели и Self

Пишу блокиратор области памяти для многопоточного приложения. Возникла некоторая проблема с указателем на Self.
Как обстоит дело. Если вызвать Unlock у ключа, то возникает ошибка где пытаюсь взять указатель от Self и получаю ошибку. Если же вызывать напрямую освобождение ключа через FreeLocker, то все работает как надо. Жду помощи по решению проблемы, заранее благодарен

Код:
constructor TLockBaseKey.Create(pLocker: PBaseLocker);
begin
  inherited Create;
  Self.pLocker := pLocker;
end;

function TLockBaseKey.Unlock: boolean;
begin
  if pLocker <> nil then
    Result := pLocker.FreeLocker(@Self)
  else
    Result := false;
end;

function TDataLocker._CreateKey(permission: TDataAccessPermission; var pOutLockKey: PLockBaseKey): integer;
  var key: TLockDataKey;
      id: integer;
begin
  key := TLockDataKey.Create(@Self, permission);
  id := queCount;
  inc(queCount);
  SetLength(queList, queCount);
  queList[id] := @key;
  pOutLockKey := @key;
  Result := id;
end;

function TDataLocker.GetLocker(permission: TDataAccessPermission; var pOutLockKey: PLockBaseKey; isSleep: boolean; sleepPeriod, timeOut: cardinal): boolean;
  var id: integer;
begin
  Result := false;
  
  id := _CreateKey(permission, pOutLockKey);
  if (id = 0) or IsLocked(pOutLockKey) then
  begin
    Result := true;
    Exit;
  end;

  if not isSleep then Exit;

  LockLoop(pOutLockKey, isSleep, sleepPeriod, timeOut);

  Result := IsLocked(pOutLockKey);  
end;

function TBaseLocker.FreeLocker(pLockKey: PLockBaseKey): boolean;
  var id: integer;
begin
  Result := false;
  if pLockKey = nil then Exit;

  for id := 0 to queCount - 1 do
    if queList[id] = pLockKey then
    begin
      _DeleteKey(id);
      Result := true;
      Exit;
    end;
end;

//тестовый код
procedure TForm1.ThreadTestBtnClick(Sender: TObject);
  var locker: TDataLocker;
      key: PLockBaseKey;
begin
  locker := TDataLocker.Create;

  key := nil;
  LogWrite(logmtInfo, 'ThreadTest', 'test is start');
  if locker.GetLocker(LockAllow_Read, key) then
    LogWrite(logmtInfo, 'ThreadTest', 'lock on read')
  else begin
    LogWrite(logmtInfo, 'ThreadTest', 'lock on read is fail');
    Exit;
  end;

  if locker.FreeLocker(key) then
//if key.Unlock then
    LogWrite(logmtInfo, 'ThreadTest', 'key is unlock')
  else begin
    LogWrite(logmtInfo, 'ThreadTest', 'key unlock is fail');
    Exit;
  end;

  locker.Free;
end;
Покапавшись еще немного понял, что проблема возникает чуть раньше. Во время обращения на pLocker. Если рассмотреть код создания ключа _CreateKey, то после записи его в очередь видно, что в queList[0] и key.pLocker записан один и тот же адресс. Я не понимаю почему так получается

Последний раз редактировалось alexprey; 09.01.2013 в 19:53.
alexprey вне форума Ответить с цитированием
Старый 09.01.2013, 19:50   #2
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

TObject и все что от него(то есть любой class)
это уже указатель на сам объект.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 09.01.2013, 19:54   #3
alexprey
Форумчанин
 
Регистрация: 25.05.2010
Сообщений: 169
По умолчанию

Пепел Феникса, в каких тогда случаях нужно использовать указатели? Для структур?

И как быть с такой конструкцией
Код:
TLockBaseKey = class
    private
      pLocker: PBaseLocker;
  end;

TBaseLocker = class
    private
      queList: array of PLockBaseKey;
      queCount: integer;
  end;

Последний раз редактировалось alexprey; 09.01.2013 в 19:56.
alexprey вне форума Ответить с цитированием
Старый 09.01.2013, 19:57   #4
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

взятие указателя будет нужно для структур и обычных переменных.
для объектов же просто привести переменную-объект/Self к указателю(а может и не надо, не помню)


посмотрите маленький пример:
Код:
TIntClass=class
 public
  i:integer;
end;

var i1,i2,i3:TIntClass;
begin
 i1:=TIntClass.Create;
 i2:=i1;
 i3:=i1;
 i1.i:=50;
 ShowMessage(IntToStr(i1.i));
 i2.i:=500;
 ShowMessage(IntToStr(i1.i));
 i1.i:=-1;
 ShowMessage(IntToStr(i3.i));
я думаю станет ясно что указатель на класс нужно выкинуть, и выйдет тогда просто
Код:
Array of TLockBaseKey
одно но правда, освобождение и создание объектов висит на ваших плечах.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.

Последний раз редактировалось Пепел Феникса; 09.01.2013 в 20:00.
Пепел Феникса вне форума Ответить с цитированием
Старый 09.01.2013, 20:05   #5
alexprey
Форумчанин
 
Регистрация: 25.05.2010
Сообщений: 169
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
одно но правда, освобождение и создание объектов висит на ваших плечах.
да это то понятно. Так как быть с такой штукой?
Код:
type
   TBaseObj = class
      parent: TExObj;
   end;
   TExObj = class
      child: array of TBaseObj;
   end;
alexprey вне форума Ответить с цитированием
Старый 09.01.2013, 20:12   #6
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

а что там не понятно?
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 09.01.2013, 20:14   #7
alexprey
Форумчанин
 
Регистрация: 25.05.2010
Сообщений: 169
По умолчанию

[Error] ThreadAPI.pas(22): Undeclared identifier: 'TBaseLocker'
alexprey вне форума Ответить с цитированием
Старый 09.01.2013, 20:16   #8
alexprey
Форумчанин
 
Регистрация: 25.05.2010
Сообщений: 169
По умолчанию

В принципе все работает и так, но вот в создании ключа @Self передается неверный и поэтому из ключа я не могу обратиться к блокиратору, который выдал этот ключ
alexprey вне форума Ответить с цитированием
Старый 09.01.2013, 20:21   #9
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

потому что надо просто Self, а не @Self, я что зря выше распинался?
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 09.01.2013, 20:25   #10
alexprey
Форумчанин
 
Регистрация: 25.05.2010
Сообщений: 169
По умолчанию

да блин не могу я просто так передать Self, потому что там конструктор принимает PBaseLocker, TBaseLocker я не могу указать, т.к. он объявлен дальше, а объявить его раньше не могу, так как тот ссылается на ключ.
alexprey вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Указатели C++ spinogryz_ua Помощь студентам 6 01.10.2012 11:26
Указатели C gignet Общие вопросы C/C++ 7 04.06.2010 23:35
указатели в С++ Aleksa_ks Помощь студентам 3 27.04.2010 19:31
Указатели papochka Общие вопросы C/C++ 2 14.11.2009 22:06
[C] массивы, указатели, двойные указатели. Iggel Общие вопросы C/C++ 5 05.05.2009 12:39