Decorator that is used for caching result.

	:param validator: function, that has following signature (decorated_function, \*args, \*\*kwargs), where \
	decorated_function - original function, args - function arguments, kwargs - function keyword arguments. \
	This function must return True if cache is valid (old result must be use if it there is one), or False - to \
	generate and to store new result. So function that always return True can be used as singleton. And function \
	that always return False won't cache anything at all. By default (if no validator is specified), it presumes \
	that cache is always valid.
	:param storage: storage that is used for caching results. see :class:`.WCacheStorage` class.

	:return: decorated function

def cache_control(validator=None, storage=None):
	""" Decorator that is used for caching result.

	:param validator: function, that has following signature (decorated_function, \*args, \*\*kwargs), where \
	decorated_function - original function, args - function arguments, kwargs - function keyword arguments. \
	This function must return True if cache is valid (old result must be use if it there is one), or False - to \
	generate and to store new result. So function that always return True can be used as singleton. And function \
	that always return False won't cache anything at all. By default (if no validator is specified), it presumes \
	that cache is always valid.
	:param storage: storage that is used for caching results. see :class:`.WCacheStorage` class.

	:return: decorated function
	"""

	def default_validator(*args, **kwargs):
		return True

	if validator is None:
		validator = default_validator

	if storage is None:
		storage = WGlobalSingletonCacheStorage()

	def first_level_decorator(decorated_function):
		def second_level_decorator(original_function, *args, **kwargs):

			validator_check = validator(original_function, *args, **kwargs)
			cache_entry = storage.get_cache(original_function, *args, **kwargs)

			if validator_check is not True or cache_entry.has_value is False:
				result = original_function(*args, **kwargs)
				storage.put(result, original_function, *args, **kwargs)
				return result
			else:
				return cache_entry.cached_value

		return decorator(second_level_decorator)(decorated_function)
	return first_level_decorator