Почему shared_ptr < T > :: use_count () возвращает long вместо типа unsigned?

Одно возможное решение использует JavaScript на клиенте.

Клиентский алгоритм:

  1. Создает случайный уникальный токен.
  2. Отправьте запрос на загрузку и включите токен в поле GET / POST.
  3. Покажите индикатор ожидания.
  4. Запустите таймер и каждую секунду или около того, найдите файл cookie с именем «fileDownloadToken» (или все, что вы решите).
  5. Если файл cookie существует и его значение соответствует токену, скройте индикатор ожидания.

Алгоритм сервера:

  1. Ищите поле GET / POST в запросе.
  2. Если у него есть непустое значение, отбросьте файл cookie (например, "fileDownloadToken ") и установите его значение в значение маркера.

Исходный код клиента (JavaScript):

function getCookie( name ) {
  var parts = document.cookie.split(name + "=");
  if (parts.length == 2) return parts.pop().split(";").shift();
}

function expireCookie( cName ) {
    document.cookie = 
        encodeURIComponent(cName) + "=deleted; expires=" + new Date( 0 ).toUTCString();
}

function setCursor( docStyle, buttonStyle ) {
    document.getElementById( "doc" ).style.cursor = docStyle;
    document.getElementById( "button-id" ).style.cursor = buttonStyle;
}

function setFormToken() {
    var downloadToken = new Date().getTime();
    document.getElementById( "downloadToken" ).value = downloadToken;
    return downloadToken;
}

var downloadTimer;
var attempts = 30;

// Prevents double-submits by waiting for a cookie from the server.
function blockResubmit() {
    var downloadToken = setFormToken();
    setCursor( "wait", "wait" );

    downloadTimer = window.setInterval( function() {
        var token = getCookie( "downloadToken" );

        if( (token == downloadToken) || (attempts == 0) ) {
            unblockSubmit();
        }

        attempts--;
    }, 1000 );
}

function unblockSubmit() {
  setCursor( "auto", "pointer" );
  window.clearInterval( downloadTimer );
  expireCookie( "downloadToken" );
  attempts = 30;
}

Пример кода сервера (PHP):

$TOKEN = "downloadToken";

// Sets a cookie so that when the download begins the browser can
// unblock the submit button (thus helping to prevent multiple clicks).
// The false parameter allows the cookie to be exposed to JavaScript.
$this->setCookieToken( $TOKEN, $_GET[ $TOKEN ], false );

$result = $this->sendFile();

Где:

public function setCookieToken(
    $cookieName, $cookieValue, $httpOnly = true, $secure = false ) {

    // See: http://stackoverflow.com/a/1459794/59087
    // See: http://shiflett.org/blog/2006/mar/server-name-versus-http-host
    // See: http://stackoverflow.com/a/3290474/59087
    setcookie(
        $cookieName,
        $cookieValue,
        2147483647,            // expires January 1, 2038
        "/",                   // your path
        $_SERVER["HTTP_HOST"], // your domain
        $secure,               // Use true over HTTPS
        $httpOnly              // Set true for $AUTH_COOKIE_NAME
    );
}

23
задан ricky m 2 April 2016 в 08:49
поделиться

1 ответ

Причина в том, что наиболее подходящим типом для счетчика этого типа является регулярное signed целое число, даже если этот счетчик никогда не станет ниже 0.

Почему счетчик должен быть unsigned? Тот факт, что он не может стать отрицательным, вовсе не является оправданием для данного текущего реального значения из unsigned для языка.

unsigned для C ++ не означает «целое число, которое не может быть отрицательным». Чтобы понять, почему это определение просто не имеет смысла, рассмотрим, что

  • Разница в два unsigned составляет unsigned
  • Добавление unsigned с signed unsigned
  • Значение unsigned никогда не превышает -1

Ничто из вышеперечисленного не имеет никакого смысла, если считать unsigned значением «неотрицательный» ».

Использование unsigned для size_t было ошибкой (см., Например, Почему size_t без знака? ), только частично * может быть исключено, потому что в 16-битной эпохе один дополнительный бит считался неправильным семантика, которую типы unsigned имеют в C ++ для такого рода использования.

К сожалению, теперь ошибка size_t не может быть исправлена ​​(из-за обратной совместимости), но зачем повторять ту же ошибку в другой не связанной области?

Обратите внимание, что, вероятно, большая ошибка была сделана просто из-за выбора имя unsigned (учитывая его реальное значение). Если бы этот тип был назван (более подходящим образом) modulo, то, вероятно, было бы более очевидно, почему использование modulo int для размера строки не имеет никакого смысла вообще.

Имя не имеет значения, то, что оно считает, является семантическим, и unsigned просто имеет неправильную семантику для счетчика или размера.

(*) Лично я не думаю, что это было достаточно веской причиной даже тогда. Если 32767 не достаточно для размера сейчас, то 65535 не будет достаточно скоро. По моему мнению, только один бит (удвоенное значение) не был приемлемой ценой для такого изгиба семантики.

РЕДАКТИРОВАТЬ

Я опубликовал видео , в котором более подробно обсуждаю, почему я считаю, что использование типа unsigned для size_t было ошибкой проектирования в C ++.

Слайды можно загрузить с http://raksy.dyndns.org/unsigned.pdf

18
ответ дан Community 2 April 2016 в 08:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: