powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / Java [игнор отключен] [закрыт для гостей] / Реализация метода BufferedInputStream.reset()
3 сообщений из 3, страница 1 из 1
Реализация метода BufferedInputStream.reset()
    #39803099
faustgreen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Метод reset():
Код: java
1.
2.
3.
4.
5.
6.
public synchronized void reset() throws IOException {
    getBufIfOpen(); // Cause exception if closed
    if (markpos < 0)
        throw new IOException("Resetting to invalid mark");
    pos = markpos;
}



Метод getBufIfOpen()
Код: java
1.
2.
3.
4.
5.
6.
private byte[] getBufIfOpen() throws IOException {
    byte[] buffer = buf;
    if (buffer == null)
        throw new IOException("Stream closed");
    return buffer;
}



Парочка вопросов:
1). Почему в методе getBufIfOpen() написано:
Код: java
1.
2.
3.
byte[] buffer = buf;
if (buffer == null)
   throw new IOException("Stream closed");


а не просто:
Код: java
1.
2.
if (buf == null)
   throw new IOException("Stream closed");



2). В методе reset есть строчка кода
Код: java
1.
getBufIfOpen(); // Cause exception if closed


т.е. метод, который должен возвращать массив, в данном методе ничего не возвращает (в других да). И получается, что метод выполняет две функции: возврат результата и проверка закрытия потока. А как же принцип "Single responsobility"?
...
Рейтинг: 0 / 0
Реализация метода BufferedInputStream.reset()
    #39803156
faustgreen
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По первому вопросу:
В классе есть метод fill():
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
    private void fill() throws IOException {
        byte[] buffer = getBufIfOpen();
        if (markpos < 0)
            pos = 0;            /* no mark: throw away the buffer */
        else if (pos >= buffer.length)  /* no room left in buffer */
            if (markpos > 0) {  /* can throw away early part of the buffer */
                int sz = pos - markpos;
                System.arraycopy(buffer, markpos, buffer, 0, sz);
                pos = sz;
                markpos = 0;
            } else if (buffer.length >= marklimit) {
                markpos = -1;   /* buffer got too big, invalidate mark */
                pos = 0;        /* drop buffer contents */
            } else {            /* grow buffer */
                int nsz = pos * 2;
                if (nsz > marklimit)
                    nsz = marklimit;
                byte nbuf[] = new byte[nsz];
                System.arraycopy(buffer, 0, nbuf, 0, pos);
                if (!bufUpdater.compareAndSet(this, buffer, nbuf)) {
                    // Can't replace buf if there was an async close.
                    // Note: This would need to be changed if fill()
                    // is ever made accessible to multiple threads.
                    // But for now, the only way CAS can fail is via close.
                    // assert buf == null;
                    throw new IOException("Stream closed");
                }
                buffer = nbuf;
            }
        count = pos;
        int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
        if (n > 0)
            count = n + pos;
}


Тут buffer используется в Atomic-ах (метод compareAndSet), походу и в методе getBufIfOpen предполагалось, что то подобное или просто какая то заготовка на будущее.
...
Рейтинг: 0 / 0
Реализация метода BufferedInputStream.reset()
    #39803626
maxkar
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
faustgreen 1). Почему в методе getBufIfOpen() написано:
Потому что там дальше написано
Код: sql
1.
return buffer;


Это никакая не заготовка а полностью корректный код. Метод разрабатывался так, чтобы он никогда не мог вернуть null. Даже в случае, если поток был закрыт асинхронно. Вот что вы собираетесь из метода возвращать, если проверяете buf на null? Какие гарантии, что до следующего чтения buf не изменился (он меняется методом close из другого потока)?

Еще нужно учитывать, что synchronized вешать на все не очень хорошо. Ладно даже с точки зрения микропроизводительности (synchronized медленнее простого чтения/volatile), это можно пережить. А вот факт, что synchronized close() будет ожидать, пока операция чтения завершится (которая заблокировалась на нижележащем потоке) пережить сложно.

С учетом требования атомарности и неблокирующиего close() это как раз прекрасный код.
faustgreen 2). В методе reset есть строчка кода ...
И получается, что метод выполняет две функции: возврат результата и проверка закрытия потока. А как же принцип "Single responsobility"?
Издержки производства. Про атомарность из пункта 1 помните? Там реализуется функциональность "вернуть буффер открытого потока". На два метода тот код не разделяется. Создать же отдельный метод для проверки (или проверить по месту) конечно можно, но даст ли это существенную выгоду? С учетом того, что метод приватный и находится в системной библиотеке такое использование вполне приемлемо.

Да и вообще, если считать "возврат результата" за responsibility, мы далеко не уйдем. Можно же так объявить все функции нарушающими SRP. Math.sin имеет две ответственности - вычисление синуса и возврат результата.
...
Рейтинг: 0 / 0
3 сообщений из 3, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / Реализация метода BufferedInputStream.reset()
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]