"""
    device_types()

Return a vector of available and implemented device types.

See also: [`DEVICE_TYPES`](@ref)
"""
function device_types()
    return DEVICE_TYPES
end

"""
    entry_device(machine::Machine)

Return the "entry" device, i.e., the device that starts CPU threads and GPU kernels, and takes input values and returns the output value.
"""
function entry_device(machine::Machine)
    return machine.devices[1]
end

"""
    strategies(t::Type{T}) where {T <: AbstractDevice}

Return a vector of available [`CacheStrategy`](@ref)s for the given [`AbstractDevice`](@ref).
The caching strategies are used in code generation.
"""
function strategies(t::Type{T}) where {T <: AbstractDevice}
    if !haskey(CACHE_STRATEGIES, t)
        error("Trying to get strategies for $T, but it has no strategies defined!")
    end

    return CACHE_STRATEGIES[t]
end

"""
    cache_strategy(device::AbstractDevice)

Returns the cache strategy set for this device.
"""
function cache_strategy(device::AbstractDevice)
    return device.cacheStrategy
end

"""
    set_cache_strategy(device::AbstractDevice, cacheStrategy::CacheStrategy)

Sets the device's cache strategy. After this call, [`cache_strategy`](@ref) should return `cacheStrategy` on the given device.
"""
function set_cache_strategy(device::AbstractDevice, cacheStrategy::CacheStrategy)
    device.cacheStrategy = cacheStrategy
    return nothing
end
