OberonCore
https://forum.oberoncore.ru/

Rider - Scroller разделение
https://forum.oberoncore.ru/viewtopic.php?f=6&t=361
Страница 1 из 1

Автор:  Сергей Губанов [ Четверг, 04 Январь, 2007 14:50 ]
Заголовок сообщения:  Rider - Scroller разделение

Райдеры (rider), т. е. считыватели и записыватели (reader и writer) могут быть либо последовательными (не позиционируемые), либо с произвольным доступом (позиционируемые). Программист может испытать затруднение при описании их типов, а именно не ясно стоит ли каждый раз заводить по два разных типа райдеров (позиционируемые и не позиционируемые) или же включить методы позиционирования (GetPosition, SetPosition,...) в один тип, но например выставлять некий булевский флаг возможности их использования. В первом случае получается слишком много типов (по 2 reader и по 2 writer), а во втором случае методы позиционирования иногда будут лишними, а тип громоздким.

Предлагаю иное решение. Вместо того чтобы включать методы позиционирования в типы reader и writer можно обзавестись типом скроллер (scroller), который и будет нести ответственность за прокрутку райдеров:

Код:
Rider = POINTER TO ABSTRACT RECORD
  (r: Rider) Available (): LONGINT, NEW, ABSTRACT
END;

Scroller = POINTER TO ABSTRACT RECORD
  (s: Scroller) MinPosition (): LONGINT, NEW, ABSTRACT;
  (s: Scroller) MaxPosition (): LONGINT, NEW, ABSTRACT;
  (s: Scroller) GetPosition (r: Rider): LONGINT, NEW, ABSTRACT;
  (s: Scroller) SetPosition (r: Rider; position: LONGINT), NEW, EMPTY
END;


где метод Available (): LONGINT показывает сколько позиций доступно для продвижения вперёд, т. е. для reader - сколько доступно для считывания и для writer - сколько доступно для записи. Бинарные считыватель и записыватель, при этом, есть просто:

Код:
Reader = POINTER TO ABSTRACT RECORD (Rider)
  (r: Reader) ReadByte (OUT a: BYTE), NEW, ABSTRACT;
  (r: Reader) ReadBytes (OUT a: ARRAY OF BYTE; offset, count: INTEGER), NEW, ABSTRACT
END;

Writer = POINTER TO ABSTRACT RECORD (Rider)
  (w: Writer) WriteByte (a: BYTE), NEW, ABSTRACT;
  (w: Writer) WriteBytes (IN a: ARRAY OF BYTE; offset, count: INTEGER), NEW, ABSTRACT
END;


Рассмотрим тип объекта-буфера. Кроме считывателей и записывателей буфер должен будет предоставлять ещё и скроллер:

Код:
Buffer = POINTER TO ABSTRACT RECORD
  (b: Buffer) NewReader (old: Reader): Reader, NEW, ABSTRACT;
  (b: Buffer) NewWriter (old: Writer): Writer, NEW, ABSTRACT;
  (b: Buffer) Scroller (): Scroller, NEW, ABSTRACT
END;


А вот, например, тип канал (channel) скроллера своих райдеров предоставлять не будет - они же у него не позиционируемые:

Код:
Channel = POINTER TO ABSTRACT RECORD
  (c: Channel) Reader (): Reader, NEW, ABSTRACT;
  (c: Channel) Writer (): Writer, NEW, ABSTRACT;
END;


Позиционируемость райдера зависит от его носителя (carrier).
Носитель либо предоставляет скроллер для своих райдеров либо не предоставляет, вот и всё.

Автор:  Илья Ермаков [ Четверг, 04 Январь, 2007 15:00 ]
Заголовок сообщения: 

По-моему, красивая и полезная идея!

Автор:  Александр Ильин [ Четверг, 04 Январь, 2007 19:33 ]
Заголовок сообщения: 

Да, идея интересная, решает определенные проблемы.
Не совсем понятно, правда, что должен возвращать метод Writer.Availabe? Объем свободного места на диске? : )

Автор:  Cardinal [ Четверг, 04 Январь, 2007 20:34 ]
Заголовок сообщения:  Re: Rider - Scroller разделение

2 Сергей Губанов

Мне кажется лишним этот тип "скроллер". Для меня - тип райдера определяется целью, то есть где-то он должен быть только последовательным, а где-то - только с произвольным доступом. Я пока не вижу пользы... пока что лишняя сущность :)

Автор:  Сергей Губанов [ Четверг, 04 Январь, 2007 21:56 ]
Заголовок сообщения: 

Александр Ильин писал(а):
...что должен возвращать метод Writer.Availabe? Объем свободного места на диске? : )


Да, не плохо бы :D.

Вообще, если места много, то можно возвращать достаточно произвольное большое число.

Метод WriteBytes может копировать содержимое в какие-либо внутренние буферы. В таком случае Writer.Availabe должен предупредить о существующем ограничении - сколько байтов можно записать за один раз.

То есть не сколько вообще места доступно, а сколько можно запихнуть байтов за один присест.

Автор:  Сергей Губанов [ Воскресенье, 07 Январь, 2007 15:16 ]
Заголовок сообщения:  Re: Rider - Scroller разделение

Сергей Губанов писал(а):
Код:
Scroller = POINTER TO ABSTRACT RECORD
  (s: Scroller) MinPosition (): LONGINT, NEW, ABSTRACT;
  (s: Scroller) MaxPosition (): LONGINT, NEW, ABSTRACT;
  (s: Scroller) GetPosition (r: Rider): LONGINT, NEW, ABSTRACT;
  (s: Scroller) SetPosition (r: Rider; position: LONGINT), NEW, EMPTY
END;


Можно немножко усовершенствовать. Объект Scroller можно сделать не имеющим состояния синглетоном (обслуживающим все райдеры из своего модуля) если передавать райдер во все его методы:
Код:
Scroller = POINTER TO ABSTRACT RECORD
  (s: Scroller) MinPosition (r: Rider): LONGINT, NEW, ABSTRACT;
  (s: Scroller) MaxPosition (r: Rider): LONGINT, NEW, ABSTRACT;
  (s: Scroller) GetPosition (r: Rider): LONGINT, NEW, ABSTRACT;
  (s: Scroller) SetPosition (r: Rider; position: LONGINT), NEW, EMPTY
END;

Ведь вся эта информация всё равно целиком содержится в райдере.
То есть на один модуль фактически будет только один объект Scroller.

Автор:  Сергей Губанов [ Среда, 12 Декабрь, 2007 13:15 ]
Заголовок сообщения:  Re: Rider - Scroller разделение

Ещё одно усовершенствование.

Если в райдер добавить некий абстрактный локатор:
Код:
public abstract class Rider
{
   public virtual object Locator { get { return null; } }
}

public abstract class Writer: Rider
{
   public abstract void WriteByte (byte b);
   public abstract void WriteBytes (byte[] bytes, int offset, int count);
   public virtual void WriteBoolean (bool x)
   ...
}

public abstract class Reader: Rider
{
   public abstract long Available { get; }
   public abstract byte ReadByte ();
   public abstract void ReadBytes (byte[] bytes, int offset, int count);
   public virtual bool ReadBool ()
   ...
}

public abstract class Scroller
{
   public virtual long MinPosition (Rider r) { return 0; }
   public virtual long MaxPosition (Rider r) { return System.Int64.MaxValue; }
   public abstract long GetPosition (Rider r);
   public abstract void SetPosition (Rider r, long position);
}

public abstract class Buffer
{
   public abstract long Length { get; }
   public abstract Scroller Scroller { get; }
   public abstract Writer NewWriter ();
   public abstract Reader NewReader ();
}

то реализация скроллера упростится:
Код:
private sealed class TheScroller: Scroller
{
   private static Locator GetLocator (Rider r)
   {
      Locator loc = r.Locator as Locator;
      if (loc != null) return loc; else throw new System.Exception("Alien rider.");
   }
   public override long MaxPosition (Rider r)
   {
      return GetLocator(r).buffer.length;
   }
   public override long GetPosition (Rider r)
   {
      return GetLocator(r).Position;
   }
   public override void SetPosition (Rider r, long position)
   {
      GetLocator(r).Position = position;
   }
}

Извините за C#, в Component Pascal это транслируется практически один в один.

Автор:  Илья Ермаков [ Воскресенье, 16 Декабрь, 2007 15:05 ]
Заголовок сообщения:  Re: Rider - Scroller разделение

Сергей, сообщаю, что давно понравившуюся Вашу идею я наконец начинаю применять :-)

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/