однобитовая манипуляция - PullRequest
       16

однобитовая манипуляция

0 голосов
/ 15 января 2011

возможно ли получить только один бит из int в C, а затем перевернуть его, не читая весь int и не записав его обратно в память?

контекст: пытаясь избежать слишком большого количества блокировок / разблокировок в pthread,

Ответы [ 6 ]

6 голосов
/ 15 января 2011

Вы не можете прочитать один бит из памяти, на самом деле вы не можете заставить процессор читать только один байт.Он всегда читает полную строку кэша, которая может иметь разные размеры для разных процессоров.

Но с языковой точки зрения вы можете использовать битовые поля http://publications.gbdirect.co.uk/c_book/chapter6/bitfields.html

1 голос
/ 19 января 2011

Вот как вы делаете это в 50 раз быстрее, чем дедушка мьютекс (мы тестировали подобные вещи). Используйте gcc атомарные операции. Вы также можете использовать атомарные операции Linux, если они включены в ваш выпуск.

typedef union _foo {
  struct {
    unsigned int a:1,
                 b:6,
                 q:2;
  } Data;
  unsigned int n32;
} TFoo;

TFoo _GlobalFoo;

SomeFuncThatChangesFoo_A(int fNewA)
{
TFoo Old, New;

  while(1) {
    // get a copy of the current state
    Old.n32 = _GlobalFoo.n32;
    New.n32 = Old.n32;
    New.Data.a = fNewA;
    // compare and swap is the atomic operation.
    // if _GlobalFoo hasn't changed since we copied it to "Old", then change _GlobalFoo to "New".
    // __sync_bool_compare_and_swap works on basic types (8 bit, 16 bit, 32 bit, 64 bit, 128 bit
    // depending upon architecture), which is why there is a union overlaying the 32 bit n32 over 
    // the actual data that the program uses, Data.
    if (__sync_bool_compare_and_swap(_GlobalFoo.n32, Old.n32, New.n32))
      break; // successfully changed 
    // if we get here, the global was changed by another thread, so we just loop back, get the new value
    // and try again.
  } // concurrency loop
}

Проницательные читатели могут подумать, что строка "Old.n32 = _GlobalFoo.n32;" может скопировать мусор в гонке, если компилятор выбрал неатомарный способ выполнить копирование. Однако __sync_bool_compare_and_swap просто потерпит неудачу из-за плохой копии текущего состояния, поэтому никакого вреда не будет.

веселит.

1 голос
/ 15 января 2011

Либо используйте наименьший тип, к которому можно обращаться атомарно (char подходит для любой здравомыслящей архитектуры, но некоторые нежелательные RISC не могут атомарно работать с отдельными байтами) и примите, что вы будете тратить некоторое пространство, используйте блокировку, или используйте правильные атомарные примитивы (в asm, встроенные gcc или типы C1x _Atomic) для атомарной арифметики на отдельных битах.

1 голос
/ 15 января 2011

Нет. Зачем, даже если вы можете прочитать один бит из памяти, вам все равно потребуется блокировка, чтобы убедиться, что это безопасно.

1 голос
/ 15 января 2011

Насколько я знаю, самая низкая единица работы - это байт. Может быть, вы можете разбить int на байты и прочитать требуемый байт из слова и изменить только этот.

0 голосов
/ 15 января 2011

Это может быть возможно, но только непереносимым, нестандартным способом и только если ваша платформа поддерживает это.В некоторых процессорах ARM (например, Cortex-M3 и M4) реализована «полоса битов», которая обеспечивает адресацию на уровне битов для областей адресного пространства.

Но в целом это наименьшая единица для чтения / записи (или эквивалентнонаименьшая адресуемая единица) char.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...