...

Source file src/go.mongodb.org/mongo-driver/bson/bsoncodec/codec_cache.go

Documentation: go.mongodb.org/mongo-driver/bson/bsoncodec

     1  // Copyright (C) MongoDB, Inc. 2017-present.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"); you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
     6  
     7  package bsoncodec
     8  
     9  import (
    10  	"reflect"
    11  	"sync"
    12  	"sync/atomic"
    13  )
    14  
    15  // Runtime check that the kind encoder and decoder caches can store any valid
    16  // reflect.Kind constant.
    17  func init() {
    18  	if s := reflect.Kind(len(kindEncoderCache{}.entries)).String(); s != "kind27" {
    19  		panic("The capacity of kindEncoderCache is too small.\n" +
    20  			"This is due to a new type being added to reflect.Kind.")
    21  	}
    22  }
    23  
    24  // statically assert array size
    25  var _ = (kindEncoderCache{}).entries[reflect.UnsafePointer]
    26  var _ = (kindDecoderCache{}).entries[reflect.UnsafePointer]
    27  
    28  type typeEncoderCache struct {
    29  	cache sync.Map // map[reflect.Type]ValueEncoder
    30  }
    31  
    32  func (c *typeEncoderCache) Store(rt reflect.Type, enc ValueEncoder) {
    33  	c.cache.Store(rt, enc)
    34  }
    35  
    36  func (c *typeEncoderCache) Load(rt reflect.Type) (ValueEncoder, bool) {
    37  	if v, _ := c.cache.Load(rt); v != nil {
    38  		return v.(ValueEncoder), true
    39  	}
    40  	return nil, false
    41  }
    42  
    43  func (c *typeEncoderCache) LoadOrStore(rt reflect.Type, enc ValueEncoder) ValueEncoder {
    44  	if v, loaded := c.cache.LoadOrStore(rt, enc); loaded {
    45  		enc = v.(ValueEncoder)
    46  	}
    47  	return enc
    48  }
    49  
    50  func (c *typeEncoderCache) Clone() *typeEncoderCache {
    51  	cc := new(typeEncoderCache)
    52  	c.cache.Range(func(k, v interface{}) bool {
    53  		if k != nil && v != nil {
    54  			cc.cache.Store(k, v)
    55  		}
    56  		return true
    57  	})
    58  	return cc
    59  }
    60  
    61  type typeDecoderCache struct {
    62  	cache sync.Map // map[reflect.Type]ValueDecoder
    63  }
    64  
    65  func (c *typeDecoderCache) Store(rt reflect.Type, dec ValueDecoder) {
    66  	c.cache.Store(rt, dec)
    67  }
    68  
    69  func (c *typeDecoderCache) Load(rt reflect.Type) (ValueDecoder, bool) {
    70  	if v, _ := c.cache.Load(rt); v != nil {
    71  		return v.(ValueDecoder), true
    72  	}
    73  	return nil, false
    74  }
    75  
    76  func (c *typeDecoderCache) LoadOrStore(rt reflect.Type, dec ValueDecoder) ValueDecoder {
    77  	if v, loaded := c.cache.LoadOrStore(rt, dec); loaded {
    78  		dec = v.(ValueDecoder)
    79  	}
    80  	return dec
    81  }
    82  
    83  func (c *typeDecoderCache) Clone() *typeDecoderCache {
    84  	cc := new(typeDecoderCache)
    85  	c.cache.Range(func(k, v interface{}) bool {
    86  		if k != nil && v != nil {
    87  			cc.cache.Store(k, v)
    88  		}
    89  		return true
    90  	})
    91  	return cc
    92  }
    93  
    94  // atomic.Value requires that all calls to Store() have the same concrete type
    95  // so we wrap the ValueEncoder with a kindEncoderCacheEntry to ensure the type
    96  // is always the same (since different concrete types may implement the
    97  // ValueEncoder interface).
    98  type kindEncoderCacheEntry struct {
    99  	enc ValueEncoder
   100  }
   101  
   102  type kindEncoderCache struct {
   103  	entries [reflect.UnsafePointer + 1]atomic.Value // *kindEncoderCacheEntry
   104  }
   105  
   106  func (c *kindEncoderCache) Store(rt reflect.Kind, enc ValueEncoder) {
   107  	if enc != nil && rt < reflect.Kind(len(c.entries)) {
   108  		c.entries[rt].Store(&kindEncoderCacheEntry{enc: enc})
   109  	}
   110  }
   111  
   112  func (c *kindEncoderCache) Load(rt reflect.Kind) (ValueEncoder, bool) {
   113  	if rt < reflect.Kind(len(c.entries)) {
   114  		if ent, ok := c.entries[rt].Load().(*kindEncoderCacheEntry); ok {
   115  			return ent.enc, ent.enc != nil
   116  		}
   117  	}
   118  	return nil, false
   119  }
   120  
   121  func (c *kindEncoderCache) Clone() *kindEncoderCache {
   122  	cc := new(kindEncoderCache)
   123  	for i, v := range c.entries {
   124  		if val := v.Load(); val != nil {
   125  			cc.entries[i].Store(val)
   126  		}
   127  	}
   128  	return cc
   129  }
   130  
   131  // atomic.Value requires that all calls to Store() have the same concrete type
   132  // so we wrap the ValueDecoder with a kindDecoderCacheEntry to ensure the type
   133  // is always the same (since different concrete types may implement the
   134  // ValueDecoder interface).
   135  type kindDecoderCacheEntry struct {
   136  	dec ValueDecoder
   137  }
   138  
   139  type kindDecoderCache struct {
   140  	entries [reflect.UnsafePointer + 1]atomic.Value // *kindDecoderCacheEntry
   141  }
   142  
   143  func (c *kindDecoderCache) Store(rt reflect.Kind, dec ValueDecoder) {
   144  	if rt < reflect.Kind(len(c.entries)) {
   145  		c.entries[rt].Store(&kindDecoderCacheEntry{dec: dec})
   146  	}
   147  }
   148  
   149  func (c *kindDecoderCache) Load(rt reflect.Kind) (ValueDecoder, bool) {
   150  	if rt < reflect.Kind(len(c.entries)) {
   151  		if ent, ok := c.entries[rt].Load().(*kindDecoderCacheEntry); ok {
   152  			return ent.dec, ent.dec != nil
   153  		}
   154  	}
   155  	return nil, false
   156  }
   157  
   158  func (c *kindDecoderCache) Clone() *kindDecoderCache {
   159  	cc := new(kindDecoderCache)
   160  	for i, v := range c.entries {
   161  		if val := v.Load(); val != nil {
   162  			cc.entries[i].Store(val)
   163  		}
   164  	}
   165  	return cc
   166  }
   167  

View as plain text