Skip to content

Passing keys between members/exists and get/set #109

@dpwiz

Description

@dpwiz
  • explGet is currently guarded by explMembers and explExists.
  • explSet is obliged to work whenever the component exists or not.

I've been thinking, what if explExists could instead return some key into the store, so explGet would know how to fetch data without traversing the store again?

This could give array-backed stores a boost:

type instance Elem (Buffer a) = a
type instance Key (Buffer a) = Ptr a -- new type family

instance _ => ExplGet m (Store a) where
  explExists :: Store a -> Int -> m (Maybe (Key (Store a)))
  explExists Store{slots} ety =
    liftIO $
      fmap (IntMap.lookup ety) $ -- `lookup` instead `member`, same O(), wraps in Maybe
        readIORef slots

  explGet :: Store a -> Key (Store a) -> m a
  explGet _store key =
    liftIO $
      peek key -- aaand... done.

instance _ => ExplSet (Store a) where
  explSet _store key value =
    liftIO $
      poke key value -- 🎉

instance _ => ExplMembers (Store a) where
  explMembers Store{slots} =
    liftIO $
      fmap (U.fromList . IntMap.toList) $ -- `toList` instead of `keys`, wraps in `(,)` (pairs have `Unbox`).
        readIORef slots

Of course this is all irrelevant for the "pure functional data structures"...

type instance Elem (Buffer a) = a
type instance Key (Map a) = Int -- The entity id is the component key

instance _ => ExplGet (Map a) where
  explExists (Map ref) ety =
    liftIO $
      fmap (bool Nothing (Just ety) . IntMap.member key) $ -- just handling the wrapping
        readIORef ref

  explGet (Map ref) key =
    liftIO $
      flip fmap (M.lookup key <$> readIORef ref) >>= -- not helpful
        maybe notFound pure

instance _ => ExplMembers (Map a) where
  explMembers (Map ref) = 
    liftIO $
      fmap (U.fromList . (\ety -> (ety, ety)) . M.keys) $ -- now this is just embarrassing 😅
        readIORef ref

So, there is a tension between

  1. pure structures -- where you can't cut any corners by passing extra data between tests and reads/writes.
  2. "unsafe" stores -- where existence witness is necessary and sufficient to go for the data directly.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions