protected function handle_invalidation_events() {
        if (!$this->definition->has_invalidation_events()) {
            return;
        }

        // Each cache stores the current 'lastinvalidation' value within the cache itself.
        $lastinvalidation = $this->get('lastinvalidation');
        if ($lastinvalidation === false) {
            // There is currently no  value for the lastinvalidation token, therefore the token is not set, and there
            // can be nothing to invalidate.
            // Set the lastinvalidation value to the current purge token and return early.
            $this->set('lastinvalidation', self::get_purge_token());
            return;
        } else if ($lastinvalidation == self::get_purge_token()) {
            // The current purge request has already been fully handled by this cache.
            return;
        }

        /*
         * Now that the whole cache check is complete, we check the meaning of any specific cache invalidation events.
         * These are stored in the core/eventinvalidation cache as an multi-dimensinoal array in the form:
         *  [
         *      eventname => [
         *          keyname => purgetoken,
         *      ]
         *  ]
         *
         * The 'keyname' value is used to delete a specific key in the cache.
         * If the keyname is set to the special value 'purged', then the whole cache is purged instead.
         *
         * The 'purgetoken' is the token that this key was last purged.
         * a) If the purgetoken matches the last invalidation, then the key/cache is not purged.
         * b) If the purgetoken is newer than the last invalidation, then the key/cache is not purged.
         * c) If the purge token is older than the last invalidation, or it has a different token component, then the
         *    cache is purged.
         *
         * Option b should not happen under normal operation, but may happen in race condition whereby a long-running
         * request's cache is cleared in another process during that request, and prior to that long-running request
         * creating the cache. In such a condition, it would be incorrect to clear that cache.
         */
        $cache = self::make('core', 'eventinvalidation');
        $events = $cache->get_many($this->definition->get_invalidation_events());
        $todelete = array();
        $purgeall = false;

        // Iterate the returned data for the events.
        foreach ($events as $event => $keys) {
            if ($keys === false) {
                // No data to be invalidated yet.
                continue;
            }

            // Look at each key and check the timestamp.
            foreach ($keys as $key => $purgetoken) {
                // If the timestamp of the event is more than or equal to the last invalidation (happened between the last
                // invalidation and now), then we need to invaliate the key.
                if (self::compare_purge_tokens($purgetoken, $lastinvalidation) > 0) {
                    if ($key === 'purged') {
                        $purgeall = true;
                        break;
                    } else {
                        $todelete[] = $key;
                    }
                }
            }
        }
        if ($purgeall) {
            $this->purge();
        } else if (!empty($todelete)) {
            $todelete = array_unique($todelete);
            $this->delete_many($todelete);
        }
        // Set the time of the last invalidation.
        if ($purgeall || !empty($todelete)) {
            $this->set('lastinvalidation', self::get_purge_token(true));
        }
    }