Last active
July 17, 2022 00:50
-
-
Save BinToss/39934d36c1016adf6f6123d8874ec08c to your computer and use it in GitHub Desktop.
C/C++ code often employs bitfields and unions (overlapping data) to save bandwidth and conserve memory. This is an example of a bitfield implemented in C#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// bitfield experiment | |
/// <summary>C definition</summary> | |
/// <remarks> | |
/// <para> | |
/// C bitfield unions' maximum size is defined by the | |
/// size of the largest Type in the bitfield union. | |
/// </para> | |
/// <para> | |
/// Each field in the union defines their bit count | |
/// with the syntax "Type Name : Int", using the colon | |
/// to signify that the following integer is the | |
/// amount of bits to occupy. | |
/// </para> | |
/// <c> | |
/// typedef struct _PH_WORK_QUEUE_ENVIRONMENT | |
/// { | |
/// LONG BasePriority : 6; // Base priority increment | |
/// ULONG IoPriority : 3; // I/O priority hint | |
/// ULONG PagePriority : 3; // Page/memory priority | |
/// ULONG ForceUpdate : 1; // Always set priorities regardless of cached values | |
/// ULONG SpareBits : 19; | |
/// } PH_WORK_QUEUE_ENVIRONMENT, *PPH_WORK_QUEUE_ENVIRONMENT; | |
/// </c> | |
/// </remarks> | |
[StructLayout(LayoutKind.Explicit, Size = 4)] | |
internal struct PH_WORK_QUEUE_ENVIRONMENT | |
{ | |
[FieldOffset(0)] private uint _; | |
public PH_WORK_QUEUE_ENVIRONMENT() | |
{ | |
_ = 0; | |
} | |
/// struct/enum definitions do not add to the struct's unmanaged size :) | |
/// We use structs instead of enums here so we don't need to convert to/from enum and uint types. | |
/// These constants are not necessary, but they do provide shorthands for longer values e.g. 19-bit sequential bitmask. | |
private struct os // Offset | |
{ | |
public const int BP = 0; // occupies s.BP bits | |
public const int IP = s.BP; // occupies s.IP bits | |
public const int PP = IP + s.IP; // occupies s.PP bits | |
public const int FU = PP + s.PP; // occupies s.FU bits | |
public const int SB = FU + s.FU; | |
private struct s // bits occupied at each offset | |
{ | |
public const int BP = 6; | |
public const int IP = 3; | |
public const int PP = 3; | |
public const int FU = 1; | |
public const int SB = 19; | |
} | |
} | |
private struct bm // sequential bitmask | |
{ | |
public const uint BP = 0b11_1111; | |
public const uint IP = 0b111; | |
public const uint PP = 0b111; | |
public const uint FU = 0b1; | |
public const uint SB = 0b111_1111_1111_1111_1111; | |
} | |
/// <summary>Base priority increment (6 bits)</summary> | |
public int BasePriority | |
{ | |
get => (int)((_ >> os.BP) & bm.BP); | |
set => _ = (((uint)value & bm.BP) << os.BP) | (_ & ~(bm.BP << os.BP)); | |
} | |
/// <summary>I/O priority hint (3 bits)</summary> | |
public uint IoPriority | |
{ | |
get => (_ >> os.IP) & bm.IP; | |
set => _ = ((value & bm.IP) << os.IP) | (_ & ~(bm.IP << os.IP)); | |
} | |
/// <summary>Page/memory priority (3 bits)</summary> | |
public uint PagePriority | |
{ | |
get => (_ >> os.PP) & bm.PP; | |
set => _ = ((value & bm.PP) << os.PP) | (_ & ~(bm.PP << os.PP)); | |
} | |
/// <summary>Always set priorities regardless of cached values (1 bit)</summary> | |
public uint ForceUpdate | |
{ | |
get => (_ >> os.FU) & bm.FU; | |
set => _ = ((value & bm.FU) << os.FU) | (_ & ~(bm.FU << os.FU)); | |
} | |
public uint SpareBits | |
{ | |
get => (_ >> os.SB) & bm.SB; | |
set => _ = ((value & bm.SB) << os.SB) | (_ & ~(bm.SB << os.SB)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment