github.com/mitghi/x@v0.0.0-20191206171256-71e86edf750d/pointers/tagged.go (about)

     1  /* MIT License
     2  *
     3  * Copyright (c) 2018 Mike Taghavi <mitghi[at]gmail.com>
     4  *
     5  * Permission is hereby granted, free of charge, to any person obtaining a copy
     6  * of this software and associated documentation files (the "Software"), to deal
     7  * in the Software without restriction, including without limitation the rights
     8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     9  * copies of the Software, and to permit persons to whom the Software is
    10  * furnished to do so, subject to the following conditions:
    11  * The above copyright notice and this permission notice shall be included in all
    12  * copies or substantial portions of the Software.
    13  *
    14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    20  * SOFTWARE.
    21   */
    22  
    23  package pointers
    24  
    25  import "unsafe"
    26  
    27  // - MARK: Pointer-Tagging section.
    28  
    29  // GetTag returns the tag value from
    30  // low-order bits.
    31  func GetTag(ptr unsafe.Pointer) uint {
    32  	return uint(uintptr(ptr) & uintptr(ArchMAXTAG))
    33  }
    34  
    35  // TaggedPointer is a function for tagging pointers.
    36  // It attaches `tag` value to the pointer `ptr` iff
    37  // `tag` <= `ArchMAXTAG` and returns the tagged pointer
    38  // along with error set to `nil`. It panics when
    39  // `tag` > `ArchMAXTAG`, I do too! It's like getting
    40  // headshot by a champagne cork.
    41  func TaggedPointer(ptr unsafe.Pointer, tag uint) (unsafe.Pointer, error) {
    42  	if tag > ArchMAXTAG {
    43  		// flip the table, not this time!
    44  		panic(EPTRINVALT)
    45  	}
    46  	return unsafe.Pointer(uintptr(ptr) | uintptr(tag)), nil
    47  }
    48  
    49  // Untag is a function for untagging pointers. It
    50  // returns a `unsafe.Pointer` with low-order bits
    51  // set to 0.
    52  func Untag(ptr unsafe.Pointer) unsafe.Pointer {
    53  	return unsafe.Pointer(uintptr(ptr) & ArchPTRMASK)
    54  }
    55  
    56  // HasTag returns whether the given pointer `ptr`
    57  // is tagged.
    58  func HasTag(ptr unsafe.Pointer) bool {
    59  	return GetTag(ptr)&ArchMAXTAG > 0
    60  }